访客设计模式是行为设计模式之一。
参观者设计模式
访问者模式是当我们必须在类似类型的对象组进行操作时使用的。使用访问者模式,我们可以将操作逻辑从对象移动到另一个类别。例如,想想一个购物车,在那里我们可以添加不同类型的项目(项目)。当我们点击支出按钮时,它计算了要支付的总金额。现在我们可以在项目类中拥有计算逻辑,或者我们可以使用访问者模式将这种逻辑移动到另一个类别。
访问者设计模式 Java 示例
要实现访客模式,首先我们将创建不同类型的项目(Elements)用于购物车。
1package com.journaldev.design.visitor;
2
3public interface ItemElement {
4
5 public int accept(ShoppingCartVisitor visitor);
6}
请注意,接受方法需要参观者论点. 我们可以有一些其他方法也具体用于项目,但为了简单,我不会进入那么多的细节,专注于参观者模式。
1package com.journaldev.design.visitor;
2
3public class Book implements ItemElement {
4
5 private int price;
6 private String isbnNumber;
7
8 public Book(int cost, String isbn){
9 this.price=cost;
10 this.isbnNumber=isbn;
11 }
12
13 public int getPrice() {
14 return price;
15 }
16
17 public String getIsbnNumber() {
18 return isbnNumber;
19 }
20
21 @Override
22 public int accept(ShoppingCartVisitor visitor) {
23 return visitor.visit(this);
24 }
25
26}
《水果》Java
1package com.journaldev.design.visitor;
2
3public class Fruit implements ItemElement {
4
5 private int pricePerKg;
6 private int weight;
7 private String name;
8
9 public Fruit(int priceKg, int wt, String nm){
10 this.pricePerKg=priceKg;
11 this.weight=wt;
12 this.name = nm;
13 }
14
15 public int getPricePerKg() {
16 return pricePerKg;
17 }
18
19 public int getWeight() {
20 return weight;
21 }
22
23 public String getName(){
24 return this.name;
25 }
26
27 @Override
28 public int accept(ShoppingCartVisitor visitor) {
29 return visitor.visit(this);
30 }
31
32}
注意在具体类中实施 accept() 方法,其 calling visit() 方法为 Visitor 并将自己传递为参数. 我们在 Visitor 界面中对不同类型的项目有 visit() 方法,这些项目将由具体的 Visitor 类实现。
1package com.journaldev.design.visitor;
2
3public interface ShoppingCartVisitor {
4
5 int visit(Book book);
6 int visit(Fruit fruit);
7}
现在我们将实施访客界面,每个项目将有自己的逻辑来计算成本。
1package com.journaldev.design.visitor;
2
3public class ShoppingCartVisitorImpl implements ShoppingCartVisitor {
4
5 @Override
6 public int visit(Book book) {
7 int cost=0;
8 //apply 5$ discount if book price is greater than 50
9 if(book.getPrice() > 50){
10 cost = book.getPrice()-5;
11 }else cost = book.getPrice();
12 System.out.println("Book ISBN::"+book.getIsbnNumber() + " cost ="+cost);
13 return cost;
14 }
15
16 @Override
17 public int visit(Fruit fruit) {
18 int cost = fruit.getPricePerKg()*fruit.getWeight();
19 System.out.println(fruit.getName() + " cost = "+cost);
20 return cost;
21 }
22
23}
让我们看看我们如何在客户端应用程序中使用访客模式示例。
1package com.journaldev.design.visitor;
2
3public class ShoppingCartClient {
4
5 public static void main(String[] args) {
6 ItemElement[] items = new ItemElement[]{new Book(20, "1234"),new Book(100, "5678"),
7 new Fruit(10, 2, "Banana"), new Fruit(5, 5, "Apple")};
8
9 int total = calculatePrice(items);
10 System.out.println("Total Cost = "+total);
11 }
12
13 private static int calculatePrice(ItemElement[] items) {
14 ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl();
15 int sum=0;
16 for(ItemElement item : items){
17 sum = sum + item.accept(visitor);
18 }
19 return sum;
20 }
21
22}
当我们在访问者模式客户端程序上运行时,我们会得到以下输出。
1Book ISBN::1234 cost =20
2Book ISBN::5678 cost =95
3Banana cost = 20
4Apple cost = 25
5Total Cost = 160
请注意,如果 accept() 方法在所有项目中的实现是相同的,但它可能会有所不同,例如,如果项目是免费的,那么就不要调用 visit() 方法。
参观者设计模式类图表
Class diagram for our visitor design pattern implementation is:
参观者模式的好处
这种模式的好处在于,如果操作逻辑发生变化,那么我们只需要在访问者实现中进行更改,而不是在所有项目类中进行更改。
参观者模式限制
访客模式的缺点是,我们在设计时应该知道返回类型的访问()方法,否则我们将不得不更改界面及其所有实现。另一个缺点是,如果有过多的访客界面实现,它很难扩展。