Шаблон посетителя: объяснения и примеры

Объектно-ориентированное программирование (ООП), которое считается подполем императивного программирования, за последние несколько лет приобрело большое значение. Возможность определить все компоненты программного проекта как объекты, которые ведут себя по-разному в зависимости от их класса, имеет ряд явных преимуществ перед другими типами программирования — главным из них является возможность легко повторно использовать уже закодированные части программы. Для разработчиков это один из самых сильных аргументов в пользу ООП.

Эта возможность повторного использования, а также советы о том, как сделать реализацию, адаптацию и тестирование созданных объектов еще проще, были описаны в книге «Паттерны проектирования: Elements of Reusable Object-Oriented Software, опубликованной разработчиками «Банды четырех». Одним из более чем 20 различных паттернов проектирования в этой книге является «паттерн посетителя» или «паттерн проектирования посетителя», о котором мы подробно расскажем в следующих разделах.

Что такое паттерн посетителя?

Паттерн посетителя или паттерн проектирования посетителя — это паттерн, который позволяет отделить алгоритм от объектной структуры, на которой он работает. Он описывает способ добавления новых операций к существующим объектным структурам без изменения самих структур. Эта характеристика делает паттерны посетителей способом реализации принципа открытости/закрытости (OCP). Этот принцип объектно-ориентированной разработки программного обеспечения гласит, что каждый программный объект — такой как модули, классы или функции — должен быть одновременно открыт для расширения, но закрыт для модификации.

Шаблон посетителя является одним из 23 шаблонов проектирования (в категории поведенческих шаблонов), описанных и опубликованных в 1994 году компьютерными учеными Эрихом Гаммой, Ричардом Хелмом, Ральфом Джонсоном и Джоном Влиссидесом. В совокупности эти разработчики известны как «Банда четырех» (сокращенно GoF), что привело к тому, что эти паттерны стали называть паттернами проектирования GoF.

Что делает паттерн проектирования «Посетитель»?

Если структура объекта состоит из нескольких несвязанных классов, разработчикам очень неудобно создавать новый подкласс для каждой операции, если им часто требуются новые операции. Результатом такого кодирования будет система с множеством различных запутанных классов, которую не только трудно понять, но и трудно управлять и редактировать при необходимости. Самым большим преимуществом паттерна посетителя является то, что «посетитель» позволяет добавлять новые, виртуальные функции в семейство классов без необходимости изменять сами классы.

Примечание

Виртуальные функции (или методы) определяют целевые функции, для которых цель может быть неизвестна на момент кодирования. Они являются важным инструментом в объектно-ориентированных системах.

Шаблон проектирования посетителя позволяет определить «объект посетителя» отдельно, с целью реализации операции, которая должна быть выполнена над одним или несколькими элементами объектной структуры. Клиенты, обращающиеся к объектной структуре, вызывают операцию диспетчеризации accept(visitor) на элементе, которая делегирует запрос принятому объекту посетителя. Затем объект посетителя может выполнить эту операцию над элементом.

Графический пример паттерна посетителя (UML-диаграмма)

Связь между доступными элементами и связанными с ними объектами посетителей с помощью паттерна проектирования посетителя лучше всего демонстрировать графически, чтобы изобразить все отношения и обмены в теоретической объектно-ориентированной системе. Лучше всего для этой цели подходит унифицированный язык моделирования (UML), который мы решили использовать в следующих диаграммах классов для нашего шаблона посетителя.

Плюсы и минусы шаблона посетителя

Шаблон посетителя — это готовый, хорошо функционирующий способ расширения уже существующих сущностей в объектно-ориентированной системе. Добавление новой операции может быть легко выполнено простым определением нового посетителя. Это также позволяет централизовать весь функциональный код. Реализация любых новых операций выполняется централизованно только в классе посетителя, а остальные классы не нужно трогать. Самое большое преимущество программы, использующей паттерн проектирования посетителя, сводится к тому, что существующий исходный код не нужно постоянно адаптировать к новым используемым объектам. Вместо этого логика распределяется между посетителями и классами посетителей, которые выступают в качестве заместителей.

Конечно, паттерны проектирования посетителей не являются идеальными во всех отношениях. Каждый, кто хочет работать с этим шаблоном, должен помнить, что даже незначительные изменения в классе элемента обычно означают, что связанные с ним классы посетителей также должны быть скорректированы. Невозможно избежать дополнительной работы при введении новых элементов впоследствии, поскольку они требуют добавления методов visit(), которые, в свою очередь, должны быть добавлены в классы ConcreteVisitor. Таким образом, фантастические возможности расширения программных сущностей связаны с немалыми усилиями.

Как использовать шаблон посетителя

Шаблон посетителя может значительно упростить повторяющиеся задачи при разработке программного обеспечения. Разработчики, работающие с объектно-ориентированными системами, должны обязательно рассмотреть возможность использования этого паттерна проектирования. С момента своего появления в 1994 году паттерн посетителя стал важным игроком на сцене программирования, и он может оказаться полезным независимо от того, какой проект программного обеспечения находится под рукой. Также нет никаких реальных ограничений в отношении языка программирования, который вы хотите использовать, если вы помните, что он лучше всего работает в объектно-ориентированной парадигме.

Популярные языки, в которых паттерны посетителей могут играть важную роль, включают:

  • C++
  • C#
  • Java
  • PHP
  • Python
  • JavaScript
  • Golang

В целях защиты вашей конфиденциальности видео не будет загружаться, пока вы не нажмете на него.

Практический пример использования шаблона посетителя

Мы понимаем, что понять использование и суть паттерна посетителя не так просто, но каждый, кто учится кодить сегодня, обязательно столкнется с этим паттерном.

Для простой и понятной аналогии из реальной ситуации паттерн посетителя часто демонстрируют на примере поездки в такси. Предположим, что клиент вызывает такси, чтобы оно доставило его к входной двери. Клиент садится в «машину для посетителей», но именно такси (точнее, водитель) полностью контролирует процесс перевозки человека.

Покупки в супермаркете — еще один распространенный пример, объясняющий, как работают схемы посещения. Человек, делающий покупки, кладет все, что ему нужно, в свою корзину, которую можно рассматривать как набор элементов из структуры объекта. Затем кассир действует как посетитель, сканируя цены и/или взвешивая каждый отдельный предмет покупки (т.е. элемент), чтобы подсчитать общую стоимость.

Пример кода для шаблона посетителя (PHP)

Следующий код представляет собой простое, базовое использование шаблона посетителя в PHP.

        return 'B';
	}
	public function getData() {
		return $this->the_data;
	}
	public function accept(Visitor $visitor) {
		$visitor-> VisitFromElementB($this);
	}
}
abstract class Visitor {
	abstract function VisitFromElementA(ElementA $elem);
	abstract function VisitFromElementB(ElementB $elem);
}
class Visitor1 extends Visitor {
	private $characteristics;
	public function getCharacs() {
		return $this->characteristics;
	}
	public function VisitFromElementA(ElementA $elem) {
		$this->characteristics = 'Info:'.$elem->getInfo();
	}
	public function VisitFromElementB(ElementB $elem) {
		$this->characteristics = 'DATA:'.$elem->getData().'!!';
	}
}
function Test() {
	write_line('Teststart');
	// Objectstructure
	$elements = array (
		new ElementA('Hello', 'New!!'),
		new ElementB('Finally.'),
	);
	$vis1 = new Visitor1();
	foreach ($elements as $element) {
		$element->accept($vis1);
		write_line('After visit from Element '.$element->getName().': '.$vis1-			>getCharacs());
}
}
function write_line($text) {
	print $text.'<br>';
}
Test();

Вывод для этого примера фрагмента кода выглядит следующим образом:

Teststart
After visit from Element A: Info:[Hello--New!!]
After visit from Element B: DATA:(Finally.)!!

Оцените статью
cdelat.ru
Добавить комментарий