扩展抽象单例类

Den*_*ovs 20 php singleton abstract-class

如果你有一个工厂类来创建某种新的对象,那个factroy类是一个单例,如下所示:

class Database_Factory extends Base_Factory {
    private static $factory;
    private $objects = array();

    public function __get($profile) {
        // check for object and return it if it's created before
    }

    public static function getInstance(){
        if (!self::$factory)
            self::$factory = new self();
        return self::$factory;
    }
}
Run Code Online (Sandbox Code Playgroud)

当某个对象需要它自己的工厂时,相同的代码会重复.所以我决定将这个工厂类抽象化,并且只为每个工厂实现特定的例程.但PHP不允许实例化抽象类.

abstract class Base_Factory {
    public static function getInstance(){
        if (!self::$factory)
            self::$factory = new self();
        return self::$factory;
    }
}
Run Code Online (Sandbox Code Playgroud)

致命错误:无法实例化抽象类Base_Factory

你会怎么做?

Fer*_*yer 36

在PHP方法中,self始终引用定义方法的类.从5.3.0版本开始,PHP支持"后期静态绑定",您可以使用该static关键字来访问重写的静态方法,以及get_called_class()在静态上下文中获取派生类名称的函数.

但是,您的设计存在一个主要缺陷:$factory定义的静态属性Base_Factory在所有派生类中共享.因此,第一次创建单例并将其存储在此属性中时,getInstance()无论使用何种派生类,所有其他调用都将返回相同的对象.

您可以使用静态字典将类名映射到单例对象:

abstract class Base_Factory {
    private static $_instances = array();
    public static function getInstance() {
        $class = get_called_class();
        if (!isset(self::$_instances[$class])) {
            self::$_instances[$class] = new $class();
        }
        return self::$_instances[$class];
    }
}
Run Code Online (Sandbox Code Playgroud)

哦,还有一件事:您正在寻找重用单例对象代码的可能性,这可能是您过度使用单例设计模式的事实!问问自己,你计划作为单身人士实施的课程是否真的是单身,如果没有用例,你可能想要拥有特定课程的多个实例.

通常,仅使用一个代表当前"应用程序上下文"的单例来提供对于此上下文的单例对象的访问器要好得多.


小智 9

PHP 5.3+

abstract class Singleton
{
    /**
     * Instance
     *
     * @var Singleton
     */
    protected static $_instance;

    /**
     * Constructor
     *
     * @return void
     */
    protected function __construct() {}

    /**
     * Get instance
     *
     * @return Singleton
     */
    public final static function getInstance() {
        if (null === static::$_instance) {
            static::$_instance = new static();
        }

        return static::$_instance;
    }
}
Run Code Online (Sandbox Code Playgroud)