При создании Singleton в PHP я удостоверяюсь, что он нельзя инстанцировать путем выполнения следующего:
class Singleton {
private function __construct() {}
private function __clone() {}
public static function getInstance() {}
}
Однако я понял, что, определяя класс, поскольку 'краткий обзор' означает, что нельзя инстанцировать. Так есть ли что-то не так с выполнением следующего вместо этого:
abstract class Singleton {
public static function getInstance() {}
}
Второй сценарий позволяет мне писать меньше строк кода, которые были бы хороши. (Не то, чтобы это на самом деле имеет большую часть значения.)
При создании синглтона в PHP объявление конструкции __
и __ clone
как закрытые гарантирует, что класс не может быть инстанциирован извне : он все еще может быть инстанцирован изнутри его объявления.
При объявлении класса как abstract
, он вообще не может быть создан ; даже не изнутри его декларации.
Это означает, что ваше решение не будет работать: во втором случае ваш метод getInstance ()
не сможет создать экземпляр класса, хотя в первом случае он может это сделать.
Нет, вы не можете использовать абстрактный класс вместо частного __construct () при создании синглтона. Но если вы намереваетесь создать абстрактный синглтон, из которого можно расширяться, вы можете сделать это следующим образом:
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; }
}
и
class Bar 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);
Однако, имейте в виду, что синглтоны очень сложно тестировать, и их следует по возможности избегать. См. Мой ответ здесь:
Нет, потому что тогда вы вообще не сможете создать экземпляр класса (даже в статическом методе getInstance). Частный конструктор в примере синглтона просто гарантирует, что только статический метод 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
для объединения сложности абстрактной фабрики с ограничениями синглтона.