Шаблон «Посетитель» выполняет операции над объектами других классов. Главной целью является сохранение разделения направленности задач отдельных классов. При этом классы обязаны определить специальный контракт, чтобы позволить использовать их Посетителям (метод «принять роль» Role::accept в примере).
Контракт, как правило, это абстрактный класс, но вы можете использовать чистый интерфейс. В этом случае, каждый посетитель должен сам выбирать, какой метод ссылается на посетителя.
Главными преимуществами применения этого паттерна являются следующие:
При этом в качестве основного недостатка выделим то, что затруднено добавление новых классов к системным «элементам», поскольку требуется объявление новой абстрактной операции в классе «Посетитель».
Использование:
Преимущества:
Недостатки:
Связи с другими паттернами
Visitor.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 }