【问题标题】:Extending a singleton class扩展单例类
【发布时间】:2010-04-06 12:54:50
【问题描述】:

我曾经像这样创建一个单例类的实例:

$Singleton = SingletonClassName::GetInstance();

对于非单例类:

$NonSingleton = new NonSingletonClassName;

我认为我们不应该区分我们如何创建一个类的实例,不管它是不是单例。如果我查看其他类的看法,我不在乎我们是否需要单例类。所以,我仍然对 php 如何处理单例类感到不舒服。我想,我一直想写:

$Singleton = new SingletonClassName;

只是另一个非单例类,这个问题有解决方案吗?

【问题讨论】:

  • 这不是一个问题——这是你抱怨你不喜欢模式的完成方式。 -1
  • 这是一个非常有道理的问题。 +1 因为 -1 不是:P

标签: php oop singleton extend


【解决方案1】:

最好反过来 - 为非单例提供factory-method,并使用以下方法获取它们的实例:

$NonSingleton = NonSingletonClassName::createInstance();

这是推荐的 Java 最佳实践(Effective Java),但它适用于大多数面向对象的语言。

【讨论】:

    【解决方案2】:

    我不推荐它,因为它会使你的代码更难理解(人们认为 new 意味着一个全新的对象)。但是我不会推荐使用单例。

    这段代码的基本思想是对单例有一个包装器。通过该包装器访问的所有函数和变量实际上都会影响单例。它并不完美,因为下面的代码没有实现很多魔术方法和 SPL 接口,但如果需要,可以添加它们

    代码

    /**
     * Superclass for a wrapper around a singleton implementation
     *
     * This class provides all the required functionality and avoids having to copy and
     * paste code for multiple singletons.
     */
    class SingletonWrapper{
        private $_instance;
        /**
         * Ensures only derived classes can be constructed
         *
         * @param string $c The name of the singleton implementation class
         */
        protected function __construct($c){
            $this->_instance = &call_user_func(array($c, 'getInstance'));
        }
        public function __call($name, $args){
            call_user_func_array(array($this->_instance, $name), $args);
        }
        public function __get($name){
            return $this->_instance->{$name};
        }
        public function __set($name, $value){
            $this->_instance->{$name} = $value;
        }
    }
    
    /**
     * A test singleton implementation. This shouldn't be constructed and getInstance shouldn't
     * be used except by the MySingleton wrapper class.
     */
    class MySingletonImpl{
        private static $instance = null;
        public function &getInstance(){
            if ( self::$instance === null ){
                self::$instance = new self();
            }
            return self::$instance;
        }
    
        //test functions
        public $foo = 1;
        public function bar(){
            static $var = 1;
            echo $var++;
        }
    }
    
    /**
     * A wrapper around the MySingletonImpl class
     */
    class MySingleton extends SingletonWrapper{
        public function __construct(){
            parent::__construct('MySingletonImpl');
        }
    }
    

    示例

    $s1 = new MySingleton();
    echo $s1->foo; //1
    $s1->foo = 2;
    
    $s2 = new MySingleton();
    echo $s2->foo; //2
    
    $s1->bar(); //1
    $s2->bar(); //2
    

    【讨论】:

      【解决方案3】:

      您不能像创建常规类实例一样创建单例。 new 将始终返回一个新实例,因此您必须让构造函数非公开,因此您必须有不同的方法从类中调用它。

      你可以在所有类上都有工厂方法,例如总是像另一个答案中所示那样做getInstance()。另一种选择是使用知道是否返回什么的Service LocatorDependency Injection Framework

      【讨论】:

        【解决方案4】:

        基于 new 关键字意味着你想要的一切都是无关紧要的。 new 创建类的新实例,这就是为什么它命名为 new :-)

        【讨论】:

          【解决方案5】:

          我知道这是一篇很老的帖子,但借助下面的链接,我更好地理解了工厂模式。

          所以如果它有助于未来徘徊。 . . .来了

          http://www.devshed.com/c/a/PHP/Design-Patterns-in-PHP-Factory-Method-and-Abstract-Factory/1/

          掌握和理解基本实现非常简单。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-12-14
            • 1970-01-01
            • 2013-07-04
            • 1970-01-01
            • 2011-03-08
            • 2014-10-27
            相关资源
            最近更新 更多