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)