===== Посетитель (Visitor) ===== [[http://webmastermsk.ru:30000/serg/patterns-php/-/blob/main/behavioral/Visitor.php|▶ code]] Шаблон «Посетитель» выполняет операции над объектами других классов. Главной целью является сохранение разделения направленности задач отдельных классов. При этом классы обязаны определить специальный контракт, чтобы позволить использовать их Посетителям (метод «принять роль» Role::accept в примере). Контракт, как правило, это абстрактный класс, но вы можете использовать чистый интерфейс. В этом случае, каждый посетитель должен сам выбирать, какой метод ссылается на посетителя. Главными преимуществами применения этого паттерна являются следующие: * Упрощается добавление новых операций к существующим в системе объектам. * Он объединяет родственные операции в едином классе. При этом в качестве основного недостатка выделим то, что затруднено добавление новых классов к системным "элементам", поскольку требуется объявление новой абстрактной операции в классе "Посетитель". **Использование:** * Когда вам нужно выполнить какую-то операцию над всеми элементами сложной структуры объектов, например, деревом. * Когда над объектами сложной структуры объектов надо выполнять некоторые не связанные между собой операции, но вы не хотите «засорять» классы такими операциями. * Когда новое поведение имеет смысл только для некоторых классов из существующей иерархии. **Преимущества:** * Упрощает добавление операций, работающих со сложными структурами объектов. * Объединяет родственные операции в одном классе. * Посетитель может накапливать состояние при обходе структуры элементов. **Недостатки:** * Паттерн не оправдан, если иерархия элементов часто меняется. * Может привести к нарушению инкапсуляции элементов. **Связи с другими паттернами** * Посетитель можно рассматривать как расширенный аналог Команды, который способен работать сразу с несколькими видами получателей. * Вы можете выполнить какое-то действие над всем деревом Компоновщика при помощи Посетителя. * Посетитель можно использовать совместно с Итератором. Итератор будет отвечать за обход структуры данных, а Посетитель – за выполнение действий над каждым её компонентом. **Visitor.php** visited; } public function visitDeveloper(Worker $developer) { $this->visited[] = $developer; } public function visitDesigner(Worker $designer) { $this->visited[] = $designer; } } interface Worker { public function work(); public function accept(WorkerVisitor $visitor); } class Developer implements Worker { public function work() { echo 'developer is working'; } public function accept(WorkerVisitor $visitor) { $visitor->visitDeveloper($this); } } class Designer implements Worker { public function work() { echo 'designer is working'; } public function accept(WorkerVisitor $visitor) { $visitor->visitDesigner($this); } } $visitor = new RecorderVisitor(); $developer = new Developer(); $designer = new Designer(); $developer->accept($visitor); $designer->accept($visitor); foreach ($visitor->getVisited() as $worker) { $worker->work(); // developer is workingde // signer is working }