Определение: инкапсулирует определенные операции, которые действуют на каждый элемент в определенную структуру данных. Он может определить новые операции, которые действуют на эти элементы, не изменяя структуру данных.
Тип: поведенческий паттерн
Классовая диаграмма:
пример:
Например, подумайте о добавлении различных типов товаров в корзину, и при нажатии на оформление заказа, это рассчитывает плату за все различные товары. Теперь логика расчета состоит в том, чтобы рассчитать цены на эти различные типы товаров. Или, другими словами, мы передаем эту логику в другой класс через режим посетителя. Давайте реализуем этот пример шаблона посетителей.
Для реализации шаблона посетителей первое, что нужно сделать, это создать класс, который можно добавить в корзину покупок, чтобы представлять различные типы предметов (элементы).
Itemlement.javapackage com.journaldev.design.visitor; public interface itemlement {public int Accece (ShoppingCartvisitor посетитель);}Обратите внимание, что метод принятия принимает посетителя в качестве параметра. Конечно, здесь есть и другие способы указать подробные продукты, но для простоты здесь нет необходимости рассматривать здесь слишком много деталей, сосредоточившись только на режиме для посетителей.
Теперь создайте несколько классов сущностей для разных продуктов.
Book.java
пакет com.journaldev.design.visitor; Книга публичного класса реализует itemlement {private int price; частная строка isbnnumber; Общественная книга (int stost, string isbn) {this.price = stost; this.isbnnumber = isbn; } public int getPrice () {return Price; } public String getisBnnumber () {return isbnnumber; } @Override public int Accept (ShoppingCartVisitor Visitor) {return Vitor.visit (this); }}Фрукты. Ява
пакет com.journaldev.design.visitor; открытый класс фруктовые реализации itemlement {private int priceperkg; частный вес; Приватное название строки; public Fruit (int pricekg, int wt, string nm) {this.priceperkg = цена; this.weight = wt; this.name = nm; } public int getPricePerkg () {return Priceperkg; } public int get -Weuess () {return Weight; } public String getName () {return this.name; } @Override public int Accept (ShoppingCartVisitor Visitor) {return Vitor.visit (this); }} Обратите внимание, что реализация метода Accept () находится в классе объектов, который вызывает метод посетителя () для передачи текущего объекта класса в качестве собственного параметра.
Здесь метод VIST (), используемый для различных типов товаров, будет реализован в классе объекта интерфейса посетителя.
ShoppingCartVisitor.java
пакет com.journaldev.design.visitor; public interface ShoppingCartVisitor {int Viate (Book Book); int view (фруктовые фрукты);}В настоящее время будет реализован интерфейс посетителей, и логика расчета своих собственных расходов для каждого продукта.
ShoppingCartVisitorImpl.java
пакет com.journaldev.design.visitor; открытый класс ShoppingCartVisitorImpl реализует ShophipVisitor {@Override public int vieft (book book) {int stost = 0; // Применить 5 $ скидка, если цена книги больше 50 if (book.getprice ()> 50) {stost = book.getprice ()-5; } else vold = book.getPrice (); System.out.println ("book isbn ::"+book.getisbnnumber ()+"stost ="+stost); рентабельная стоимость; } @Override public int vieft (фрукты фруктов) {int ost = fruit.getPricePerkg ()*fruit.getweight (); System.out.println (fruit.getName () + "stost =" + stost); рентабельная стоимость; }}Теперь посмотрим, как использовать его в программе.
ShoppingCartClient.java
пакет com.journaldev.design.visitor; public Class ShoppingCartClient {public static void main (string [] args) {itemElement [] items = new itemlement [] {новая книга (20, "1234"), новая книга (100, "5678"), новый фрукт (10, 2, "Банана"), Новый фрукт (5, 5, "5," Apple "); int total = CalculatePrice (элементы); System.out.println ("Общая стоимость ="+total); } private static int canculateprice (itemlement [] items) {shoppingCartvisitor Visitor = new ShoppingCartVisitorImpl (); int sum = 0; для (элемент itemlement: элементы) {sum = sum + item.accept (посетитель); } return sum; }}При запуске вышеуказанной программы мы получаем следующий вывод.
Книга ISBN :: 1234 Стоимость = 20Book ISBN :: 5678 Стоимость = 95BANANA стоимость = 20ply стоимость = 25total стоимость = 160
Обратите внимание, что реализация здесь, кажется, такая же, как метод Accept () для всех продуктов, но она также может отличаться. Например, если продукт пуст, он может выполнять логические проверки и больше не вызывает метод VIST ().
Преимущества режима посетителей:
Соответствует принципу единой ответственности: в любом сценарии, когда режим посетителя применим, операции, которые необходимо инкапсулировать в посетителе в классе элементов, должны быть операциями, которые имеют мало общего с самим классом элемента и являются изменчивыми. С одной стороны, использование режима посетителя соответствует принципу единой ответственности, а с другой стороны, поскольку инкапсулированные операции обычно изменчивы, когда происходят изменения, расширение изменяющейся части может быть достигнуто без изменения самого класса элементов.
Хорошая масштабируемость: классы элементов могут расширять различные операции, принимая разных посетителей.
Применимые сценарии для режима посетителей:
Если в объекте есть некоторые операции, которые не связаны с объектом (или слабо связаны), и чтобы избежать этих операций, загрязняющих объект, вы можете использовать режим посетителя, чтобы инкапсулировать эти операции в посетителя.
Если в группе объектов есть аналогичные операции, чтобы избежать большого количества дублированного кода, эти дубликаты также могут быть инкапсулированы в посетителя.
Тем не менее, режим для посетителей не такой идеальный, и он также имеет роковые недостатки: добавление новых классов элементов сложнее. Через код шаблона посетителя мы видим, что в классе посетителей каждый класс элементов имеет соответствующий метод обработки. То есть каждый класс элементов должен быть добавлен для изменения класса для посетителей (также включая подкласс или класс реализации класса для посетителей), что является довольно неприятным для изменения. То есть, когда количество классов элементов неясно, режим посетителя следует использовать с осторожностью. Следовательно, режим посетителя более подходит для рефакторирования существующих функций. Например, если были определены основные функции проекта, данные классов элементов были в основном определены и не будут изменяться. Все, что изменится, это соответствующие операции в этих элементах. В настоящее время мы можем использовать режим посетителя для рефакторирования исходного кода, чтобы исходные функции могли быть изменены без изменения каждого класса элементов.
Суммировать:
Как GOF, автор книги «Образец проектирования», описывает режим посетителя: в большинстве случаев вам необходимо использовать режим посетителя, но как только он вам понадобится, он действительно нуждается в нем. Конечно, это только для настоящих больших парней. В действительности (по крайней мере, в окружающей среде, в которой я нахожусь), многие люди часто зависимы от моделей дизайна. При использовании шаблона дизайна они никогда не рассматривают, подходит ли образец, который они используют, подходит для этого сценария, но часто просто хотят показать свою способность управлять объектно-ориентированным дизайном. Если у вас есть этот менталитет при программировании, вы часто злоупотребляете шаблоном дизайна. Поэтому при обучении шаблонов дизайна вы должны понимать применимость шаблонов. Необходимо использовать шаблон, потому что вы понимаете его преимущества, а не использовать шаблон, потому что вы понимаете его недостатки; Вместо того, чтобы использовать шаблон, потому что вы не понимаете его недостатков, а не для использования шаблона, потому что вы не понимаете его преимуществ.