Вот что Эрих Гамма , один из изобретателей модели Синглтона, говорит об этом:
«Я за то, чтобы отбросить синглтон. Его использование почти всегда вызывает запах дизайна»
Итак, вместо Singleton я предлагаю использовать Dependency Injection .
Создайте экземпляр Helper, прежде чем создавать значение $ this. Затем установите вспомогательный экземпляр на $ this экземпляра извне, либо через метод setter, либо через конструктор.
В качестве альтернативы создайте брокера-помощника, который знает, как создавать экземпляры помощников по имени, и передавать его в экземпляр $ this:
class HelperBroker
{
protected $helpers = array();
public function getHelper($name)
{
// check if we have a helper of this name already
if(!array_key_exists($name, $this->helpers)) {
// create helper and store for later subsequent calls
$this->helpers[$name] = new $name;
}
return $this->helpers[$name];
}
}
Таким образом, вы можете лениво загружать помощников по мере необходимости и никогда не получите второй экземпляр без использования Singleton. Передайте экземпляр брокера каждому классу, которому нужны помощники.
Пример с одним помощником
$helper = new Helper;
$someClass = new Something($helper);
и
class Something
{
protected $helper;
public function __construct($helper)
{
$this->helper = $helper;
}
public function useHelper()
{
$return = $this->helper->doSomethingHelpful();
}
}
Внутри $ то, что вы теперь можете хранить и обращаться к экземпляру помощника напрямую. Вам не нужно ничего создавать. На самом деле $ $ даже не нужно беспокоиться о том, как создается экземпляр помощника, потому что мы даем $ что-то все, что ему может понадобиться заранее.
Теперь, если вы хотите использовать более одного помощника в $ someClass, вы должны использовать тот же принцип:
$helper1 = new Helper;
$helper2 = new OtherHelper;
$something = new Something($helper1, $helper2);
Этот список будет довольно длинным, чем больше зависимостей вы вставляете заранее. Возможно, мы не хотим создавать экземпляры всех помощников все время. Вот где HelperBroker вступает в игру. Вместо того, чтобы передавать каждый помощник в качестве готового экземпляра в $ нечто, мы внедряем объект, который знает, как создавать помощников, а также отслеживает их.
$broker = new HelperBroker;
$something = new Something($broker);
и
class Something
{
protected $helperBroker;
public function __construct($broker)
{
$this->helperBroker = $broker;
}
public function doSomethingHelpful()
{
$return = $this->getHelper('foo')->doSomethingHelpful();
}
public function doSomethingElse()
{
$return = $this->getHelper('bar')->doSomethingElse();
}
}
Теперь $ что-то может получить необходимых помощников, когда они нужны от брокера. Кроме того, любой класс, которому требуется доступ к помощникам, теперь больше не должен беспокоиться о том, как создать помощника, поскольку эта логика инкапсулирована внутри брокера.
$broker = new HelperBroker;
$something = new Something($broker);
$other = new Other($broker);
Посредник также гарантирует, что у вас есть только один экземпляр помощника, потому что, когда был создан экземпляр помощника, он сохраняется внутри посредника и возвращается при последующих вызовах. Это решает вашу первоначальную проблему, что вы не хотите повторно использовать помощников. Это также не заставляет ваших помощников знать что-либо о том, как управлять собой в глобальном состоянии, как это делает Синглтон. Вместо этого вы, помощники, можете сосредоточиться на своей ответственности: помогать. Это чисто, просто и многократно.