扩展抽象单例类

2022-08-30 18:59:06

如果你有一个工厂类来创建某种类型的新对象,并且该 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;
    }
}

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

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

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

你会怎么做?


答案 1

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

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

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

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];
    }
}

哦,还有一件事:您正在寻找一种对单例对象重用代码的可能性这一事实可能是您过度使用单例设计模式的事实的线索!问问自己,您计划作为单例实现的类是否真的是单例,以及您是否没有可能希望拥有特定类的多个实例的用例。

通常,最好只使用一个单例来表示当前的“应用程序上下文”,该上下文为相对于此上下文的单例对象提供访问器。


答案 2

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;
    }
}

推荐