я раньше создавал экземпляр singleton-класса как это:
$Singleton = SingletonClassName::GetInstance();
и для не singleton-класс:
$NonSingleton = new NonSingletonClassName;
я думаю, что мы не должны дифференцироваться, как мы создаем экземпляр класса, является ли это одиночным элементом или нет. если я смотрю в восприятии другого класса, я не забочусь, нужен ли класс нам singleton-класс или нет. таким образом, я все еще довольный тем, как php рассматривают singleton-класс. я думаю, и я всегда хочу записать:
$Singleton = new SingletonClassName;
просто другой не singleton-класс, существует ли решение этой проблемы?
Я бы не рекомендовал это сделало бы ваш код намного сложнее для понимания (люди думают, что новый означает совершенно новый объект). Но тогда я бы не стал отказываться от использования синглтонов.
Основная идея этого кода состоит в том, что вокруг синглтона есть оболочка. Все функции и переменные, к которым осуществляется доступ через эту оболочку, фактически влияют на синглтон. Он не идеален, поскольку в приведенном ниже коде не реализовано много волшебных методов и интерфейсов SPL, но они могут быть добавлены при необходимости
Код
/**
* Superclass for a wrapper around a singleton implementation
*
* This class provides all the required functionality and avoids having to copy and
* paste code for multiple singletons.
*/
class SingletonWrapper{
private $_instance;
/**
* Ensures only derived classes can be constructed
*
* @param string $c The name of the singleton implementation class
*/
protected function __construct($c){
$this->_instance = &call_user_func(array($c, 'getInstance'));
}
public function __call($name, $args){
call_user_func_array(array($this->_instance, $name), $args);
}
public function __get($name){
return $this->_instance->{$name};
}
public function __set($name, $value){
$this->_instance->{$name} = $value;
}
}
/**
* A test singleton implementation. This shouldn't be constructed and getInstance shouldn't
* be used except by the MySingleton wrapper class.
*/
class MySingletonImpl{
private static $instance = null;
public function &getInstance(){
if ( self::$instance === null ){
self::$instance = new self();
}
return self::$instance;
}
//test functions
public $foo = 1;
public function bar(){
static $var = 1;
echo $var++;
}
}
/**
* A wrapper around the MySingletonImpl class
*/
class MySingleton extends SingletonWrapper{
public function __construct(){
parent::__construct('MySingletonImpl');
}
}
Примеры
$s1 = new MySingleton();
echo $s1->foo; //1
$s1->foo = 2;
$s2 = new MySingleton();
echo $s2->foo; //2
$s1->bar(); //1
$s2->bar(); //2
Лучше быть наоборот - предоставить фабричный метод для несинглтонов и получить их экземпляры, используя:
$NonSingleton = NonSingletonClassName::createInstance();
Это рекомендуемый передовой метод для Java (в Эффективная Java ), но он применим к большинству объектно-ориентированных языков.
На основании того, что ключевое слово новое
означает все, что вы хочу не имеет значения. new
создает новый экземпляр класса, поэтому он назвал new : -)
Вы не можете создать синглтон так же, как обычный экземпляр класса. new
всегда будет возвращать новый экземпляр, поэтому у вас должен быть закрытый конструктор и, следовательно, у вас должны быть другие средства для его вызова из класса.
У вас могут быть фабричные методы для всех классов, например всегда выполняйте getInstance ()
, как показано в другом ответе. Другой вариант - использовать Service Locator и Dependency Injection Framework , который знает, что возвращать.