5

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

$Singleton = SingletonClassName::GetInstance();

对于非单例类:

$NonSingleton = new NonSingletonClassName;

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

$Singleton = new SingletonClassName;

只是另一个非单例类,有没有解决这个问题的方法?

4

5 回答 5

3

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

$NonSingleton = NonSingletonClassName::createInstance();

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

于 2010-04-06T12:59:34.870 回答
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
于 2010-04-06T13:39:36.580 回答
1

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

您可以在所有类上都有工厂方法,例如,总是getInstance()像另一个答案中所示那样做。另一种选择是使用知道是否返回什么的服务定位器依赖注入框架。

于 2010-04-06T13:04:34.423 回答
1

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

于 2010-04-06T13:06:28.510 回答
1

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

因此,如果它有助于未来徘徊。. . . 开始

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

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

于 2012-06-17T18:11:29.500 回答