【问题标题】:How to emulate __destruct() in a static class?如何在静态类中模拟 __destruct()?
【发布时间】:2011-08-08 15:24:30
【问题描述】:

我为自己的框架编写了一个简单的配置类。

有一些简单的函数,如get()set()loadFile()。 但是所有的函数和变量都是静态的。

现在我想实现一个自动保存机制。我想创建一个实例(在我的 init() 函数中),其 __destruct() 将调用静态 destruct() 函数:

<?php

class Config
{
  static private $autoSave;
  static public function get() {} /* set(), save(), load(), etc. */

  static public function init($autoSave)
  {
    self::$autoSave = $autoSave;
    new Config();
  }
  static public function destruct()
  {
    if (self::$autoSave)
      self::save();
  }

  public function __destruct()
  {
    Config::destruct();
  }
}

?>

在这种情况下是否有更好的解决方案或者我的设计模式完全错误?

【问题讨论】:

    标签: php design-patterns static class-design


    【解决方案1】:

    在这种情况下是否有更好的解决方案或者我的设计模式完全错误?

    析构函数仅在对象上调用,而不是静态类。

    相反,您可以将您的类从静态转换为常规,以便创建它的实例。然后它将具有析构函数。此外,它使您的代码更易于重用和测试。

    此外,您还可以为 __get__setArrayAccess 实现魔术方法,这通常对于轻松存储和访问数据非常有用,就像配置一样。

    或者,您可以将析构函数对象添加到静态类成员以实现您要查找的内容:

    class ConfigDestructor
    {
      public function __destruct()
      {
        Config::destruct();
      }
    }
    
    class Config
    {
      static private $destructorInstance;
      static private $autoSave;
      static public function get() {} /* set(), save(), load(), etc. */
    
      static public function init($autoSave)
      {
        if (null === self::$destructorInstance) 
            self::$destructorInstance = new ConfigDestructor();
    
        self::$autoSave = $autoSave;
      }
      static public function destruct()
      {
        if (self::$autoSave)
          self::save();
      }
    }
    

    仅供参考:您写道您想添加自动保存功能。 __destruct()register_shutdown_function 都有一个共同的差距:

    注意:脚本的工作目录可以在某些Web服务器下的关闭功能内改变,例如阿帕奇。

    您应该指定一个绝对路径来访问要保存到的文件。另请参阅:PHP file creation/write within destructor

    【讨论】:

    • 我已经知道该功能,但我认为还有其他方法。而且我也为路径建立了一个解决方法。我只是通过加载来保存文件句柄。顺便说一句,起初我的课程没有任何静态函数,我已将其转换为上面的代码。
    • @user603003:如果您真的想保持静态,我只是添加了一种使用ConfigDestructor 对象的方法。但我强烈建议您不要通常使用静态类函数,而是将配置作为对象工作。
    • 所以我使用了我的第一个代码,其中包含 100% 面向对象的函数。
    【解决方案2】:

    在您的 init 方法中,添加对 register_shutdown_function 的调用:

    register_shutdown_function(array('Config', 'destruct'));
    

    【讨论】:

      【解决方案3】:

      你看过register_shutdown_function吗?您可以将您的方法添加到脚本的关闭部分。

      看看Singleton pattern 也是值得的。

      【讨论】:

      • 是的,但我不想为配置类保留该功能。
      • 如果您担心的话,您可能注册了多个关机功能。注册一个不会取消注册以前注册的,如果这就是您所说的“保留”。
      • 好吧,如果其中一个关闭函数调用 exit() 其他函数不再被调用 - __destruct() 对这种行为免疫。
      【解决方案4】:

      您可以在自动注册时创建此静态类的实例。

      $instance = array();
      spl_autoload_register(function ($class)
      {
          ...
          global $instance;
          if ($isStatic) $instance[] = new $class();
          ...
      });
      

      这对我来说很好。

      ...对于那些不喜欢可读代码的人(未经测试):

      class staticInstances()
      {
          private static $list = array();
      
          public static function add($class)
          {
              self::$list[] = new $class();
          }
      
          function __distruct()
          {
              foreach (self::$list as $class)
                  unset(self::$list);
          }
      }
      $staticInstances = new staticInstances();
      
      spl_autoload_register(function ($class)
      {
          ...
          if ($isStatic) staticInstances::add($class);
          ...
      });
      

      【讨论】:

      • 哇,即使是在我问这个问题 1 年后的答案。您的代码可能运行良好,但它使用了全局变量——这是程序员应该避免的。
      • 然后用静态函数 addclass() 构建一个类并实例化这个类。但在我看来,这太过分了。这是我唯一的全局变量。记得亲亲尽可能经常地。这并不意味着懒惰。
      猜你喜欢
      • 1970-01-01
      • 2010-12-21
      • 1970-01-01
      • 2014-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多