Java 中的访问者设计模式

访客设计模式是行为设计模式之一。

参观者设计模式

访问者模式是当我们必须在类似类型的对象组进行操作时使用的。使用访问者模式,我们可以将操作逻辑从对象移动到另一个类别。例如,想想一个购物车,在那里我们可以添加不同类型的项目(项目)。当我们点击支出按钮时,它计算了要支付的总金额。现在我们可以在项目类中拥有计算逻辑,或者我们可以使用访问者模式将这种逻辑移动到另一个类别。

访问者设计模式 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: visitor design pattern, visitor pattern class diagram

参观者模式的好处

这种模式的好处在于,如果操作逻辑发生变化,那么我们只需要在访问者实现中进行更改,而不是在所有项目类中进行更改。

参观者模式限制

访客模式的缺点是,我们在设计时应该知道返回类型的访问()方法,否则我们将不得不更改界面及其所有实现。另一个缺点是,如果有过多的访客界面实现,它很难扩展。

Published At
Categories with 技术
comments powered by Disqus