在PHP中创建单例时,我可以使用抽象类而不是私有的_构造()吗?
在PHP中创建单例时,我确保不能通过执行以下操作来实例化它:在PHP中创建单例时,我可以使用抽象类而不是私有的_构造()吗?,php,singleton,abstract-class,Php,Singleton,Abstract Class,在PHP中创建单例时,我确保不能通过执行以下操作来实例化它: class Singleton { private function __construct() {} private function __clone() {} public static function getInstance() {} } 然而,我意识到将类定义为“抽象”意味着它不能被实例化。那么,改为执行以下操作是否有任何错误: abstract class Singleton { p
class Singleton {
private function __construct() {}
private function __clone() {}
public static function getInstance() {}
}
然而,我意识到将类定义为“抽象”意味着它不能被实例化。那么,改为执行以下操作是否有任何错误:
abstract class Singleton {
public static function getInstance() {}
}
第二种情况允许我编写更少的代码行,这会很好。(并不是说它实际上有多大区别。)不,因为这样您就根本无法实例化该类(即使在静态getInstance方法中也不行)。singleton示例中的私有构造函数只是确保只有来自同一类的静态getInstance方法才能访问构造函数。在PHP中创建singleton时,将
\uu构造
和\uu克隆
声明为私有可确保类不能从外部实例化:它仍然可以从其声明内部实例化
将类声明为抽象时,它根本不能实例化;甚至从它的声明里面也没有
这意味着您的解决方案将不起作用:在第二种情况下,您的getInstance()
方法将无法实例化该类,而在第一种情况下它可以这样做。如果您的Singleton::getInstance()
应该返回另一个类的实例,那么它可能会起作用
abstract class Singleton {
public static function getInstance() {
static $instance = null;
if ( is_null($instance) ) {
$instance = new StdClass; // a different class than 'abstract class Singleton'
$instance->x = time();
}
return $instance;
}
}
$obj = Singleton::getInstance();
但我会觉得很困惑。有点像误用abstract
将抽象工厂的复杂性与单例约束结合起来。不,在创建单例时,不能使用抽象类而不是私有构造()。但是,如果您打算创建一个抽象的单例,从中进行扩展,您可以这样做:
abstract class Singleton
{
private static $_instances;
public static function getInstance()
{
$className = get_called_class(); // As of PHP 5.3
if(! isset(self::$_instances[$className] )) {
self::$_instances[$className] = new $className();
}
return self::$_instances[$className];
}
protected function __construct( ) {}
final private function __clone( ) {}
final private function __wakeup( ) {}
}
class Foo extends Singleton {
protected $_foo = 1;
public function setFoo($i) { $this->_foo = $i; }
public function getFoo() { return $this->_foo; }
}
然后,您可以从Singleton进行如下扩展:
abstract class Singleton
{
private static $_instances;
public static function getInstance()
{
$className = get_called_class(); // As of PHP 5.3
if(! isset(self::$_instances[$className] )) {
self::$_instances[$className] = new $className();
}
return self::$_instances[$className];
}
protected function __construct( ) {}
final private function __clone( ) {}
final private function __wakeup( ) {}
}
class Foo extends Singleton {
protected $_foo = 1;
public function setFoo($i) { $this->_foo = $i; }
public function getFoo() { return $this->_foo; }
}
及
和操纵:
$foo1 = Foo::getInstance();
$foo1->setFoo(5);
$foo2 = Foo::getInstance();
var_dump($foo2);
$bar1 = Bar::getInstance();
var_dump($bar1);
echo new ReflectionObject($foo2);
echo new ReflectionObject($bar1);
但是,请记住,单例测试很难进行单元测试,如果可能的话应该避免。有关一些背景信息,请参见我的回答:
我并没有试图创建一个抽象的单例类,但我相信有人会发现这很有用,谢谢。我知道单例的问题,我更喜欢使用DI或静态注册表和工厂;这个问题是为了满足我的好奇心!然而,我显然应该先测试一下我的想法,从其他评论中可以看出。+1是一个完全可用的例子。很酷,不知道PHP中的抽象,它是在PHP5中引入的,这些家伙不会浪费时间,总是添加新的很酷的特性。谢谢,和+1发布了这么有趣的问题。@Marco PHP5从7年前的2004年7月开始发布。这不是什么新功能。