扩展抽象单例类
如果您有一个创建某种新对象的工厂类,并且该工厂类是一个单例,如下所示:
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
你会做什么?
If you had a factory class that creates new objects of some kind, and that factroy class is a singleton, like this:
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;
}
}
The same code repeats anytime where some object needs it's own factory. So i decided to make this factory class abstract and implement only specific routines for each factory. But PHP does not allow to instantiate abstract class.
abstract class Base_Factory {
public static function getInstance(){
if (!self::$factory)
self::$factory = new self();
return self::$factory;
}
}
Fatal error: Cannot instantiate abstract class Base_Factory
What would you do?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
在 PHP 方法中,
self
始终引用定义该方法的类。从 5.3.0 版本开始,PHP 支持“后期静态绑定”,您可以使用static
关键字来访问重写的静态方法,以及函数get_ Called_class()
获取静态上下文中派生类的名称。但是,您的设计有一个重大缺陷:
Base_Factory
中定义的静态属性$factory
在所有派生类之间共享。因此,第一次创建单例并将其存储在此属性中时,对getInstance()
的所有其他调用都将返回相同的对象,无论使用什么派生类。您可以使用静态字典将类名映射到单例对象:
哦,还有一件事:您正在寻找重用单例对象代码的可能性这一事实可能表明您过度使用了单例设计模式!问问自己,您计划作为单例实现的类是否真的是单例,以及是否不存在您可能希望拥有特定类的多个实例的用例。
通常,最好只使用一个代表当前“应用程序上下文”的单例,该单例为相对于该上下文为单例的对象提供访问器。
In PHP methods,
self
always refers to the class where the method is defined. Since version 5.3.0, PHP supports “late static binding”, where you can use thestatic
keyword to access overridden static methods, as well as the functionget_called_class()
to get the name of the derived class in static context.However, your design has a major flaw: The static property
$factory
defined inBase_Factory
is shared across all derived classes. Therefore, the first time a singleton is created and stored in this property, all other calls togetInstance()
will return the same object, no matter what derived class is used.You could use a static dictionary mapping class names to singleton objects:
Oh, one more thing: The fact that you are looking for a possibility to re-use code for singleton objects could be a cue to the fact that you are over-using the singleton design pattern! Ask yourself if the classes you are planning to implement as singletons really are singletons and if there will be no use case where you might want to have multiple instances of the particular class.
Often it is much better to use just one singleton representing the current “application context” that provides accessors for objects that are singletons with respect to this context.
PHP 5.3+
PHP 5.3+
仅 PHP >= 5.3
PHP >= 5.3 only
在像这样的简单类中注册您的单例
然后执行此
输出
Register your singletons in a simple class like this
Then do this
Output
根据定义,抽象类不能像任何其他面向对象语言一样在 PHP 中实例化。所以你的 Base_Factory 应该是接口而不是抽象类。
PHP 手册中:“不允许创建已定义为抽象的类的实例。”
By definition abstract classess cannot be instantiated in PHP like any other object oriented languages. So your Base_Factory should be interface instead of abstract class.
From the PHP manual: "It is not allowed to create an instance of a class that has been defined as abstract."
那么您可以进行检查以确保调用该函数的类不是 Base_Factory。
然后使用 $this 而不是 self 来引用当前对象而不是当前类。
Well you could do a check to make sure the class calling the function isn't the Base_Factory.
Then use $this instead of self to refer to the current object instead of the current class.