【问题标题】:Return a reference to an instance of an object in PHP在 PHP 中返回对对象实例的引用
【发布时间】:2010-02-04 22:19:15
【问题描述】:

我有一个单例工厂,并希望它返回对对象实例的引用,以便我可以使用单例工厂来销毁实例,并且在我的代码中的其他地方没有实例可以生存。

我希望能够做到的示例:

$cat = CatFactory::getInstance();
$cat->talk(); //echos 'meow'
CatFactory::destructInstance();
$cat->talk(); //Error: Instance no longer exists

【问题讨论】:

    标签: php oop reference singleton factory


    【解决方案1】:

    这可以工作:

    <?php
    class FooFactory
    {
      private static $foo;
    
      private function __construct()
      {
      }
    
      public static function getInstance()
      {
        return self::$foo ? self::$foo : (self::$foo = new FooFactory());
      }
    
      public static function destroyInstance()
      {
        self::$foo = null;
      }
    
      public function __call($fn, $args)
      {
        if (!method_exists(self::$foo, $fn) || $fn[0] == "_")
          throw new BadMethodCallException("not callable");
    
        call_user_func_array(array(self::$foo, $fn), $args);
      }
    
      # function hidden since it starts with an underscore
      private function _listen()
      {
      }
    
      # private function turned public by __call
      private function speak($who, $what)
      {
        echo "$who said, '$what'\n";
      }
    
    }
    
    $foo = FooFactory::getInstance();
    $foo->speak("cat", "meow");
    $foo->_listen();                 # won't work, private function
    FooFactory::destroyInstance();
    $foo->speak("cow", "moo");       # won't work, instance destroyed
    ?>
    

    显然这是一个 hack。

    【讨论】:

    • 我很难理解这是如何工作的。请您详细说明一下好吗?
    • 通过将方法标记为私有,它会触发神奇的__call 方法。如果private static $instance 没有被销毁,该函数本质上只是将调用转发到私有函数。这有点像在每个公共函数的顶部添加if (!self::$instance) throw new Exception();
    【解决方案2】:

    根据unset 的文档,我认为这是不可能的。您不能实际上销毁一个对象,只能销毁它的句柄。如果周围的其他变量仍然持有引用,则该对象将继续存在。

    【讨论】:

      【解决方案3】:

      你可以通过让你的 Cat 对象强制执行一个私有的 $destroyed 属性来完成你想要的。 PHP 5 默认通过引用传递对象,所以你不必担心那部分。

      【讨论】:

        【解决方案4】:

        解决方法是创建一个猫类

        class cat
        {
          public $cat;
        
          public function __construct()
          {
            $this->cat = CatFactory::getInstance();
          }
        
          public function __destruct()
          {
            CatFactory::destructInstance();
          }
        
        }
        
        $cat = new cat();
        $cat->cat->talk();
        $cat->cat->talk();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-04-07
          • 1970-01-01
          • 1970-01-01
          • 2017-06-02
          • 1970-01-01
          • 1970-01-01
          • 2021-10-15
          • 2011-08-10
          相关资源
          最近更新 更多