Интересные разделы:

Шаблон Service Locator

Обнавлено: 03.02.2020

В этой статье подробно описан шаблон Service Locator

Как и было обещано, в этой статье следует поговорить о логике создания объекта, а не о конкретных примерах ООП. Но некоторые из моделей, обсуждаемых здесь, скрывают хитроумные решения о создании объектов, если не сами объекты. Синглтонский мотив не может быть привлечен к ответственности. Логика создания интегрированных объектов совершенно однозначна. В модели Factory создание семейств продуктов группируется по разным конкретным классам производителей. Но как вы выбираете конкретного производителя? Аналогичная трудность возникает при использовании модели Prototype. Эти две модели участвуют в создании объектов, но они задерживают решение о том, какой конкретный объект (или группу объектов) создавать. Решение о выборе конкретного производителя обычно принимается на основании заданного значения параметра конфигурации. Этот параметр может находиться в базе данных, в файле конфигурации или в файле на сервере (например, в файле конфигурации на уровне каталогов на сервере Apache; обычно он называется .htaccess) или даже может быть закодирован как переменная или свойство в PHP. А поскольку конфигурация приложения в PHP должна изменяться для каждого запроса, инициализация сценария должна быть максимально простой. Поэтому я обычно прибегаю к встроенной кодировке значений флагов конфигурации в коде PHP. Вы можете сделать это вручную или написать скрипт для автоматической генерации файла класса. Вот пример класса конфигурации, который включает параметр для указания типа календарного протокола.

class Settings
{
	static $COMMSTYPE = 'Bloggs';
}

И теперь, если есть значение параметра, вы можете создать класс, который использует эти параметры при принятии решения, какой объект CommsManager предоставить по запросу. В таких случаях шаблон синглтона часто используется в сочетании с заводским шаблоном.

class AppConfig
{
    private static $instance;
    private $commsManager;

    private function __construct()
    {
        $this->init();
    }

    private function init()
    {
        switch (Settings::$COMMSTYPE) {
            case 'Mega':
                $this->commsManager = new MegaCommsManager();
                break;
            default:
                $this->commsManager = new BloggsCommsManager();
        }
    }

    public static function  getInstance() : AppConfig
    {
        if(empty(self::$instance)){
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function getCommsManager() : CommsManager
    {
        return $this->commsManager();
    }
}

Класс AppConfig является стандартным одноэлементным классом, поэтому мы можем легко получить ссылку на экземпляр AppConfig в любом месте нашей программы, и он всегда будет ссылкой на один и тот же экземпляр. Метод init () вызывается конструктором класса и поэтому выполняется только один раз во время выполнения программы. Этот метод проверяет значение свойства Settings::$COMMSTURE и создает экземпляр указанного объекта CommsManager, как показано ниже. Теперь в скрипте вы можете получить объект типа CommsManager и работать с ним, даже не зная его конкретных реализаций или конкретных классов, которые он создает.

$commsMgr = AppConfig::getInstance()->getCommsManager();
print $commsMgr->getApptEncoder()->encode();

Класс AppConfig автоматически организует поиск и создание компонентов и, следовательно, действует как типичный пример применения модели Service Locator. Это элегантная модель, хотя она создает зависимость в менее легкой форме, чем прямая инициализация. Во всех классах, которые используют такой монолитный сервис, созданный в соответствии с этой моделью, необходимо вызывать его явно, что связывает их с остальной частью системы в более широком контексте. Вот почему некоторые предпочитают выбирать другой подход.