Java中的访问者设计模式–示例教程

访客模式行为设计模式之一 。 当我们必须对一组相似类型的对象执行操作时,将使用访问者模式。 借助访问者模式,我们可以将操作逻辑从对象移动到另一个类。

例如,假设有一个购物车,我们可以在其中添加不同类型的项目(元素),当我们单击“结帐”按钮时,它将计算要支付的总金额。 现在我们可以将计算逻辑包含在项目类中,或者可以使用访问者模式将此逻辑移到另一个类中。 让我们在访问者模式示例中实现此功能。

为了实现访客模式,首先,我们将创建用于购物车的不同类型的项目(元素)。

ItemElement.java
package com.journaldev.design.visitor;

public interface ItemElement {

	public int accept(ShoppingCartVisitor visitor);
}

注意,accept方法接受Visitor参数,我们可以有一些其他特定于项目的方法,但为简单起见,我不打算讨论太多细节,而仅关注于访问者模式。

让我们为不同类型的项目创建一些具体的类。

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);
	}

}
水果.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);
	}

}

注意具体类中accept()方法的实现,它调用Visitor的visit()方法并将其自身作为参数传递。

我们在Visitor界面中具有针对不同项目类型的visit()方法,将由具体的visitor类实现。

ShoppingCartVisitor.java
package com.journaldev.design.visitor;

public interface ShoppingCartVisitor {

	int visit(Book book);
	int visit(Fruit fruit);
}

现在,我们将实现访客界面,并且每个项目都有其自己的逻辑来计算费用。

ShoppingCartVisitorImpl.java
package com.journaldev.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.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, "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()方法的返回类型,否则我们将不得不更改接口及其所有实现。 另一个缺点是,如果访问者接口的实现过多,则很难扩展。


翻译自: https://www.javacodegeeks.com/2013/08/visitor-design-pattern-in-java-example-tutorial.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值