Odwiedzający (visitor) - wzorzec projektowy (design pattern) - java
1. Cel:
Wzorzec Odwiedzający (visitor) to świetny sposób na oddzielenie algorytmu od struktury obiektu.
Klasa Visitor zawiera zmiany i specjalizacje zamiast zmiany oryginalnego obiektu.
2. Problem:
Chcemy mieć klasę ale osługę nowych funkcji chcemy mieć w jednym miescu.
Mamy grupę obiektów i operację którą chcemy na nich wykonać.
Logikę obieków chcemy mieć w osobnej klasie.
3. Rozwiązanie:
Wzorzec Odwiedzający (visitor) implementuje interface który obsługuje każdy element i klasę wizytator dla niego.
Wizytator wie o każdym elemencie dla którego jest zaimplementowany.
Zamiast zmieniać każdy element mamy klasę wizytatora którą zmieniamy.
4. Diagram klas wzorca Odwiedzający (visitor):
5. Implementacja:
Klasa testująca:
public class VisitorTest { public static void main(String[] args) { Element[] items = new Element[]{ new Book(20, "Pan Tadeusz"), new Book(50, "Wzorce projektowe Java"), new Vegetable(3, 4, "Kapusta"), new Vegetable(5, 2, "Marchewka")}; int total = calculatePrice(items); System.out.println("Całkowita Cena = " + total); } private static int calculatePrice(Element[] items) { ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl(); int sum = 0; for (Element item : items) { sum = sum + item.accept(visitor); } return sum; } }
implemetacja Klasy Element:
public interface Element { int accept(ShoppingCartVisitor visitor); } public class Book implements Element { private int price; private String title; public Book(int cost, String title) { this.price = cost; this.title = title; } public int getPrice() { return price; } public String getTitle() { return title; } @Override public int accept(ShoppingCartVisitor visitor) { return visitor.visit(this); } } public class Vegetable implements Element { private int pricePerKg; private int weight; private String name; public Vegetable(int pricePerKg, int weight, String name) { this.pricePerKg = pricePerKg; this.weight = weight; this.name = name; } 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); } }
implementacja wizytatora:
public interface ShoppingCartVisitor { int visit(Book book); int visit(Vegetable vegetable); } public class ShoppingCartVisitorImpl implements ShoppingCartVisitor { @Override public int visit(Book book) { int cost; // powyżej 50 zł 5 zł rabatu if (book.getPrice() > 30) { cost = book.getPrice() - 3; } else { cost = book.getPrice(); } System.out.println("Tytuł::" + book.getTitle() + " cena =" + cost); return cost; } @Override public int visit(Vegetable vegetable) { int cost = vegetable.getPricePerKg() * vegetable.getWeight(); System.out.println(vegetable.getName() + " cena = " + cost); return cost; } }
Wynik programu:
Tytuł::Pan Tadeusz cena =20
Tytuł::Wzorce projektowe Java cena =47
Kapusta cena = 12
Marchewka cena = 10
Całkowita Cena = 89
6. Zastosowanie w kodzie java:
- javax.lang.model.element.Element i javax.lang.model.element.ElementVisitor
- javax.lang.model.type.TypeMirror i javax.lang.model.type.TypeVisitor
|