Здесь показаны различия между двумя версиями данной страницы.
|
php:shablony_proektirovanija:behavioral_patterns:visitor [2023/08/17 23:18] werwolf создано |
php:shablony_proektirovanija:behavioral_patterns:visitor [2023/08/17 23:19] (текущий) werwolf |
||
|---|---|---|---|
| Строка 3: | Строка 3: | ||
| [[http://webmastermsk.ru:30000/serg/patterns-php/-/blob/main/behavioral/Visitor.php|▶ code]] | [[http://webmastermsk.ru:30000/serg/patterns-php/-/blob/main/behavioral/Visitor.php|▶ code]] | ||
| - | Шаблон «Посетитель» выполняет операции над объектами других классов. Главной целью является сохранение разделения\\ | + | Шаблон «Посетитель» выполняет операции над объектами других классов. Главной целью является сохранение разделения направленности задач отдельных классов. При этом классы обязаны определить специальный контракт, чтобы позволить использовать их Посетителям (метод «принять роль» Role::accept в примере). |
| - | направленности задач отдельных классов. При этом классы обязаны определить специальный контракт, чтобы позволить\\ | + | |
| - | использовать их Посетителям (метод «принять роль» Role::accept в примере). | + | |
| - | Контракт, как правило, это абстрактный класс, но вы можете использовать чистый интерфейс. В этом случае, каждый\\ | + | Контракт, как правило, это абстрактный класс, но вы можете использовать чистый интерфейс. В этом случае, каждый посетитель должен сам выбирать, какой метод ссылается на посетителя. |
| - | посетитель должен сам выбирать, какой метод ссылается на посетителя. | + | |
| Главными преимуществами применения этого паттерна являются следующие: | Главными преимуществами применения этого паттерна являются следующие: | ||
| Строка 15: | Строка 12: | ||
| * Он объединяет родственные операции в едином классе. | * Он объединяет родственные операции в едином классе. | ||
| - | При этом в качестве основного недостатка выделим то, что затруднено добавление новых классов к системным "элементам",\\ | + | При этом в качестве основного недостатка выделим то, что затруднено добавление новых классов к системным "элементам", поскольку требуется объявление новой абстрактной операции в классе "Посетитель". |
| - | поскольку требуется объявление новой абстрактной операции в классе "Посетитель". | + | |
| **Использование:** | **Использование:** | ||
| * Когда вам нужно выполнить какую-то операцию над всеми элементами сложной структуры объектов, например, деревом. | * Когда вам нужно выполнить какую-то операцию над всеми элементами сложной структуры объектов, например, деревом. | ||
| - | * Когда над объектами сложной структуры объектов надо выполнять некоторые не связанные между собой операции, но вы не\\ | + | * Когда над объектами сложной структуры объектов надо выполнять некоторые не связанные между собой операции, но вы не хотите «засорять» классы такими операциями. |
| - | хотите «засорять» классы такими операциями. | + | |
| * Когда новое поведение имеет смысл только для некоторых классов из существующей иерархии. | * Когда новое поведение имеет смысл только для некоторых классов из существующей иерархии. | ||
| Строка 38: | Строка 33: | ||
| **Связи с другими паттернами** | **Связи с другими паттернами** | ||
| - | * Посетитель можно рассматривать как расширенный аналог Команды, который способен работать сразу с несколькими видами\\ | + | * Посетитель можно рассматривать как расширенный аналог Команды, который способен работать сразу с несколькими видами получателей. |
| - | получателей. | + | |
| * Вы можете выполнить какое-то действие над всем деревом Компоновщика при помощи Посетителя. | * Вы можете выполнить какое-то действие над всем деревом Компоновщика при помощи Посетителя. | ||
| - | * Посетитель можно использовать совместно с Итератором. Итератор будет отвечать за обход структуры данных, а Посетитель\\ | + | * Посетитель можно использовать совместно с Итератором. Итератор будет отвечать за обход структуры данных, а Посетитель – за выполнение действий над каждым её компонентом. |
| - | – за выполнение действий над каждым её компонентом. | + | |
| + | **Visitor.php** | ||
| + | |||
| + | <code php> | ||
| + | |||
| + | <?php | ||
| + | |||
| + | interface WorkerVisitor | ||
| + | { | ||
| + | public function visitDeveloper(Worker $worker); | ||
| + | |||
| + | public function visitDesigner(Worker $worker); | ||
| + | } | ||
| + | |||
| + | class RecorderVisitor implements WorkerVisitor | ||
| + | { | ||
| + | private array $visited = []; | ||
| + | |||
| + | public function getVisited(): array | ||
| + | { | ||
| + | return $this->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 | ||
| + | } | ||
| + | |||
| + | |||
| + | </code> | ||