Java中的访客设计模式
访客设计模式是行为设计模式之一。
访客设计模式
当我们必须对一组相似类型的对象执行操作时,将使用访问者模式。
借助访问者模式,我们可以将操作逻辑从对象移动到另一个类。
例如,考虑一个购物车,我们可以其中添加不同类型的项目(元素)。
当我们点击结帐按钮时,它将计算要支付的总金额。
现在,我们可以将计算逻辑包含在项目类中,或者可以使用访问者模式将此逻辑移到另一个类中。
让我们在访问者模式示例中实现此功能。
访客设计模式Java示例
为了实现访客模式,首先,我们将创建用于购物车的不同类型的项目(元素)。
ItemElement.java
package com.theitroad.design.visitor; public interface ItemElement { public int accept(ShoppingCartVisitor visitor); }
请注意,accept方法采用Visitor参数。
我们可以有一些其他特定于项目的方法,但为简单起见,我将不讨论太多细节,而仅关注访问者模式。
让我们为不同类型的项目创建一些具体的类。
Book.java
package com.theitroad.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.theitroad.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()方法的实现,它调用Visitor的visit()方法并将其自身作为参数传递。
我们在Visitor界面中具有针对不同项目类型的visit()方法,将由具体的visitor类实现。
ShoppingCartVisitor.java
package com.theitroad.design.visitor; public interface ShoppingCartVisitor { int visit(Book book); int visit(Fruit fruit); }
现在,我们将实现访客界面,并且每个项目都有其自己的逻辑来计算费用。
ShoppingCartVisitorImpl.java
package com.theitroad.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; } }
让我们看看如何在客户端应用程序中使用访问者模式示例。
ShoppingCartClient.java
package com.theitroad.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()方法的返回类型,否则我们将不得不更改接口及其所有实现。
另一个缺点是,如果访问者接口的实现过多,则很难扩展。