Автор оригинала: Pankaj Kumar.
Шаблон дизайна посетителей-это один из поведенческих шаблонов дизайна.
Шаблон Дизайна Посетителей
Шаблон посетителя используется, когда нам нужно выполнить операцию над группой объектов аналогичного типа. С помощью шаблона посетителя мы можем переместить операционную логику из объектов в другой класс.
Например, подумайте о корзине покупок, в которую мы можем добавлять различные типы товаров (элементов). Когда мы нажимаем на кнопку “Оформить заказ”, она рассчитывает общую сумму, подлежащую оплате. Теперь мы можем использовать логику вычисления в классах элементов или перенести эту логику в другой класс, используя шаблон посетителя. Давайте реализуем это в нашем примере шаблона посетителя.
Образец Дизайна посетителя Пример Java
Чтобы реализовать шаблон посетителя, в первую очередь мы создадим различные типы товаров (элементов), которые будут использоваться в корзине покупок.
Чтобы реализовать шаблон посетителя, в первую очередь мы создадим различные типы товаров (элементов), которые будут использоваться в корзине покупок.
package com.journaldev.design.visitor; public interface ItemElement { public int accept(ShoppingCartVisitor visitor); }
Обратите внимание, что метод accept принимает аргумент посетителя. У нас могут быть и другие методы, также специфичные для предметов, но для простоты я не буду вдаваться в такие подробности и сосредоточусь только на шаблоне посетителя.
Давайте создадим несколько конкретных классов для различных типов предметов.
Давайте создадим несколько конкретных классов для различных типов предметов.
package com.journaldev.design.visitor; public class Book implements ItemElement { private int price; private String isbnNumber; public Book(int cost, String isbn){ this.price=cost; this.isbnNumber=isbn; } public int getPrice() { return price; } public String getIsbnNumber() { return isbnNumber; } @Override public int accept(ShoppingCartVisitor visitor) { return visitor.visit(this); } }
Давайте создадим несколько конкретных классов для различных типов предметов.
package com.journaldev.design.visitor; public class Fruit implements ItemElement { private int pricePerKg; private int weight; private String name; public Fruit(int priceKg, int wt, String nm){ this.pricePerKg=priceKg; this.weight=wt; this.name = nm; } public int getPricePerKg() { return pricePerKg; } public int getWeight() { return weight; } public String getName(){ return this.name; } @Override public int accept(ShoppingCartVisitor visitor) { return visitor.visit(this); } }
Обратите внимание на реализацию метода accept() в конкретных классах, его вызов метода visit() Посетителя и передачу себя в качестве аргумента.
У нас есть метод visit() для различных типов элементов в интерфейсе посетителя, который будет реализован конкретным классом посетителя.
У нас есть метод visit() для различных типов элементов в интерфейсе посетителя, который будет реализован конкретным классом посетителя.
package com.journaldev.design.visitor; public interface ShoppingCartVisitor { int visit(Book book); int visit(Fruit fruit); }
Теперь мы внедрим интерфейс для посетителей, и у каждого товара будет своя логика расчета стоимости.
Теперь мы внедрим интерфейс для посетителей, и у каждого товара будет своя логика расчета стоимости.
package com.journaldev.design.visitor; public class ShoppingCartVisitorImpl implements ShoppingCartVisitor { @Override public int visit(Book book) { int cost=0; //apply 5$ discount if book price is greater than 50 if(book.getPrice() > 50){ cost = book.getPrice()-5; }else cost = book.getPrice(); System.out.println("Book ISBN::"+book.getIsbnNumber() + " cost ="+cost); return cost; } @Override public int visit(Fruit fruit) { int cost = fruit.getPricePerKg()*fruit.getWeight(); System.out.println(fruit.getName() + " cost = "+cost); return cost; } }
Давайте посмотрим, как мы можем использовать пример шаблона посетителя в клиентских приложениях.
Давайте посмотрим, как мы можем использовать пример шаблона посетителя в клиентских приложениях.
package com.journaldev.design.visitor; public class ShoppingCartClient { public static void main(String[] args) { ItemElement[] items = new ItemElement[]{new Book(20, "1234"),new Book(100, "5678"), new Fruit(10, 2, "Banana"), new Fruit(5, 5, "Apple")}; int total = calculatePrice(items); System.out.println("Total Cost = "+total); } private static int calculatePrice(ItemElement[] items) { ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl(); int sum=0; for(ItemElement item : items){ sum = sum + item.accept(visitor); } return sum; } }
Когда мы запускаем клиентскую программу с шаблоном посетителя выше, мы получаем следующий вывод.
Book ISBN::1234 cost =20 Book ISBN::5678 cost =95 Banana cost = 20 Apple cost = 25 Total Cost = 160
Обратите внимание, что реализация, если метод accept() во всех элементах одинакова, но может отличаться, например, может быть логика для проверки, свободен ли элемент, тогда вообще не вызывайте метод visit ().
Диаграмма Классов Шаблонов дизайна посетителей
Диаграмма классов для реализации шаблона дизайна для посетителей-это:
Преимущества шаблона для посетителей
Преимущество этого шаблона заключается в том, что если логика работы меняется, то нам нужно вносить изменения только в реализацию посетителя, а не делать это во всех классах элементов.
Еще одним преимуществом является то, что добавить новый элемент в систему легко, для этого потребуются изменения только в интерфейсе посетителя и реализации, и существующие классы элементов не будут затронуты.
Ограничения по шаблону посетителей
Недостатком шаблона посетителя является то, что мы должны знать тип возврата методов visit() во время проектирования, иначе нам придется изменить интерфейс и все его реализации. Еще одним недостатком является то, что при слишком большом количестве реализаций интерфейса посетителя его трудно расширить.
Это все для шаблона дизайна посетителей, дайте мне знать, если я что-нибудь пропустил. Пожалуйста, поделитесь им также с другими, если вам понравилось.