Visitor Entwurfsmuster in Java
Das Visitor-Muster wird verwendet, wenn wir eine Operation an einer Gruppe ähnlicher Objekte durchführen müssen. Mit Hilfe des Visitor-Musters können wir die operationale Logik von den Objekten in eine andere Klasse verlagern. Denken Sie zum Beispiel an einen Einkaufswagen, in den wir verschiedene Arten von Artikeln (Elemente) hinzufügen können. Wenn wir auf den Checkout-Button klicken, berechnet er die zu zahlende Gesamtsumme. Jetzt können wir die Berechnungslogik in den Artikelklassen haben, oder wir können diese Logik mit Hilfe des Visitor-Musters in eine andere Klasse verlagern. Implementieren wir dies in unserem Beispiel des Visitor-Musters.
Visitor Entwurfsmuster Java Beispiel
Um das Visitor-Muster zu implementieren, werden wir zuerst verschiedene Arten von Artikeln (Elemente) erstellen, die im Einkaufswagen verwendet werden sollen. ItemElement.java
package com.journaldev.design.visitor;
public interface ItemElement {
public int accept(ShoppingCartVisitor visitor);
}
Beachten Sie, dass die Accept-Methode ein Visitor-Argument nimmt. Wir könnten auch einige andere Methoden spezifisch für Artikel haben, aber der Einfachheit halber gehe ich nicht so sehr ins Detail und konzentriere mich nur auf das Visitor-Muster. Lassen Sie uns einige konkrete Klassen für verschiedene Arten von Artikeln erstellen. Book.java
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);
}
}
Fruit.java
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);
}
}
Beachten Sie die Implementierung der Accept()-Methode in konkreten Klassen, sie ruft die Visit()-Methode des Visitors auf und übergibt sich selbst als Argument. Wir haben eine Visit()-Methode für verschiedene Arten von Artikeln in der Visitor-Schnittstelle, die von der konkreten Visitor-Klasse implementiert wird. ShoppingCartVisitor.java
package com.journaldev.design.visitor;
public interface ShoppingCartVisitor {
int visit(Book book);
int visit(Fruit fruit);
}
Jetzt werden wir die Visitor-Schnittstelle implementieren und jeder Artikel wird seine eigene Logik haben, um die Kosten zu berechnen. ShoppingCartVisitorImpl.java
package com.journaldev.design.visitor;
public class ShoppingCartVisitorImpl implements ShoppingCartVisitor {
@Override
public int visit(Book book) {
int cost=0;
//5$ Rabatt anwenden, wenn der Buchpreis höher als 50 ist
if(book.getPrice() > 50){
cost = book.getPrice()-5;
}else cost = book.getPrice();
System.out.println("Buch ISBN::"+book.getIsbnNumber() + " kostet ="+cost);
return cost;
}
@Override
public int visit(Fruit fruit) {
int cost = fruit.getPricePerKg()*fruit.getWeight();
System.out.println(fruit.getName() + " kostet = "+cost);
return cost;
}
}
Lassen Sie uns sehen, wie wir das Visitor-Muster-Beispiel in Client-Anwendungen verwenden können. ShoppingCartClient.java
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, "Banane"), new Fruit(5, 5, "Apfel")};
int total = calculatePrice(items);
System.out.println("Gesamtkosten = "+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;
}
}
Wenn wir oben genanntes Visitor-Muster-Client-Programm ausführen, erhalten wir folgende Ausgabe.
- Buch ISBN::1234 kostet =20
- Buch ISBN::5678 kostet =95
- Banane kostet = 20
- Apfel kostet = 25
- Gesamtkosten = 160
Beachten Sie, dass die Implementierung der Accept()-Methode in allen Artikeln gleich ist, sie könnte jedoch unterschiedlich sein, zum Beispiel könnte es eine Logik geben, um zu prüfen, ob der Artikel kostenlos ist, dann die Visit()-Methode gar nicht erst aufzurufen.
Vorteile des Visitor-Musters
Der Vorteil dieses Musters ist, dass, wenn sich die Logik der Operation ändert, wir nur in der Visitor-Implementierung Änderungen vornehmen müssen und nicht in allen Artikelklassen. Ein weiterer Vorteil ist, dass das Hinzufügen eines neuen Artikels zum System einfach ist, es erfordert Änderungen nur in der Visitor-Schnittstelle und Implementierung und die bestehenden Artikelklassen werden nicht beeinträchtigt.
Einschränkungen des Visitor-Musters
Der Nachteil des Visitor-Musters ist, dass wir die Rückgabetypen der Visit()-Methoden zum Zeitpunkt des Entwurfs kennen müssen, sonst müssen wir die Schnittstelle und alle ihre Implementierungen ändern. Ein weiterer Nachteil ist, dass es schwierig wird, zu erweitern, wenn es zu viele Implementierungen der Visitor-Schnittstelle gibt. Das ist alles zum Visitor-Entwurfsmuster, lassen Sie uns wissen, wenn wir etwas übersehen haben. Teilen Sie es auch mit anderen, wenn es Ihnen gefallen hat.