java中的访问者模式 – 例子辅导

原文链接 作者:Pankaj Kumar 译者:f0tlo <1357654289@qq.com>

访问者模式是一种行为设计模式。访问者模式被用在针对一组相同类型对象的操作。优点是,可以把针对此对象的操作逻辑转移到另外一个类上。

例如,思考一下添加不同类型商品的购物车,当点击结算的时候,它计算出所有不同商品需付的费用。现在,计算逻辑即为计算这些不同类型商品的价格。或者说通过访问者模式我们把此逻辑转移到了另外一个类上面。让我们实现这个访问者模式的例子。

为了实现访问者模式,最先需要做的是创建能够被添加到购物车中代表不同类型商品(itemElement)的类。

ItemElement.java

package com.journaldev.design.visitor;

public interface ItemElement {

	public int accept(ShoppingCartVisitor visitor);
}

注意,accept方法接受访问者作为参数。当然这儿还有其他的一些方法来指定详细的商品,但为了简化,此处没用过多的考虑细节,只关注访问者模式。

现在创建一些不同商品的实体类。

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

}

注意,accept()方法的实现是在实体类中,它调用访问者的visit()方法传递当前类对象作为自己的参数。
此处针对不同类型的商品所使用的visit()方法将会在访问者接口的实体类中被实现。

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()方法的返回值的类型在设计系统式就需要明确。不然,就需要修改访问者的接口以及所有接口实现。另外如果访问者接口的实现太多,系统的扩展性就会下降。

时间: 2024-12-21 12:42:07

java中的访问者模式 – 例子辅导的相关文章

详解Java设计模式编程中的访问者模式_java

定义:封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作.类型:行为类模式类图: 例子:例如,思考一下添加不同类型商品的购物车,当点击结算的时候,它计算出所有不同商品需付的费用.现在,计算逻辑即为计算这些不同类型商品的价格.或者说通过访问者模式我们把此逻辑转移到了另外一个类上面.让我们实现这个访问者模式的例子. 为了实现访问者模式,最先需要做的是创建能够被添加到购物车中代表不同类型商品(itemElement)的类. ItemElement.ja

举例讲解设计模式中的访问者模式在Java编程中的运用_java

访问者(Visitor)模式:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作.访问者模式的结构图如下: 通过上图可以看到他有如下角色:抽象访问者(Visitor)角色:定义接口,声明一个或多个访问操作. 具体访问者(ConcreteVisitor)角色:实现抽象访问者所声明的接口,也就是抽象访问者所声明的各个访问操作. 抽象元素(Visitable)角色:声明一个接受操作,接受一个访问者对象作为一个参数. 具体元素结点(Concrete

Java中的状态模式实例教程

原文链接 作者:Pankaj Kumar 译者:f0tlo <1357654289@qq.com> 状态模式是一种行为设计模式.适用于当对象的内在状态改变它自身的行为时. 如果想基于对象的状态来改变自身的行为,通常利用对象的状态变量及if-else条件子句来扮演针对对象的不同行为.状态模式Context(环境)和State(状态)分离的方式既保证状态与行为的联动变化,又使得这种变化是条理明晰且松耦合的. Context是包含了状态引用的类,此引用指向一个状态的具体实现.并且帮助把对状态的请求委

java中的工厂模式

举两个例子以快速明白Java中的工厂模式: 女娲抟土造人 话说:"天地开辟,未有人民,女娲抟土为人."女娲需要用土造出一个个的人,但在女娲造出人之前,人的概念只存在于女娲的思想里面. 女娲造人,这就是简单工厂模式的应用. 首先,在这个造人的思想里面,有几个重要的角色:女娲本身.抽象的人的概念和女娲所造出的一个个具体的人. 1.)女娲是一个工厂类,也就是简单工厂模式的核心角色.         2.)具休的一个个的人,包括张三,李四等.这些人便是简单工厂模式里面的具体产品角色 3.)抽象

JAVA设计模式之访问者模式详解_java

在阎宏博士的<JAVA与模式>一书中开头是这样描述访问者(Visitor)模式的: 访问者模式是对象的行为模式.访问者模式的目的是封装一些施加于某种数据结构元素之上的操作.一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变. 分派的概念 变量被声明时的类型叫做变量的静态类型(Static Type),有些人又把静态类型叫做明显类型(Apparent Type):而变量所引用的对象的真实类型又叫做变量的实际类型(Actual Type).比如: 复制代码 代码如下: List lis

JAVA中的命令模式实例教程

命令模式是一种行为模式,因此,它处理的是对象的行为.命令模式为系统中不同的对象提供中性化的交流媒介.根据GoF的定义,命令模式是: 通过封装一组完全不相关的对象相互之间的的交互及通讯来完成松耦合. 允许某一个对象的行为的变化是独立于其他对象的. 在企业级应用中,命令模式是非常有用的,它使得多个对象可以相互交流.如果一些对象与另一些对象直接交流,系统组件之间是紧耦合的方式.这种方式导致系统具有更高的可维护性,可扩展的灵活性变得很低.命令模式专注于提供一个调解人介于需要交流的对象之间来帮助完成对象间

Java中的策略模式实例教程

策略模式是一种行为模式.用于某一个具体的项目有多个可供选择的算法策略,客户端在其运行时根据不同需求决定使用某一具体算法策略. 策略模式也被称作政策模式.实现过程为,首先定义不同的算法策略,然后客户端把算法策略作为它的一个参数.使用这种模式最好的例子是Collection.sort()方法了,它使用Comparator对象作为参数.根据Comparator接口不同实现,对象会被不同的方法排序.详细介绍请看java中的排序对象. 本文例子是,完成一个简单地购物车,两种付款策略可供选择,一为信用卡,另

Java中的模板模式

原文链接 作者:Pankaj Kumar   译者:f0tlo <1357654289@qq.com> 模板模式是一种行为设计模式,它的实现思路是,创建一个桩方法,并且定义一些步骤让子类来实现.模板方法定义了一个算法的执行步骤,或者说能够提供一种默认的实现,这种实现概括一部分子类或者全部子类的共同部分. 举一个例子帮助理解,假设提供一种造房子的算法.算法的步骤就是模拟造房子的过程:建地基.建支撑,最后添加墙和窗户 – 1. Fundation,2. Pillars,3. Walls,4. Wi

Java中的外观模式

外观模式(Facade) 外观模式的意图是:为子系统提供一个接口,便于它的使用. 解释: 简单的说,外观模式就是封装多个上层应用需要的方法,使得上层调用变得简单,为上层提供简单的 接口,是设计模式中一种比较简单的设计思想,但是,也是最常用的一种设计模式. 举例: 当 你想吃橘子的时候,你需要做那几件事呢? 1:去买橘子 2:剥橘子 3:吃橘子 这样去一步一步的调用各个方法是不是觉得很麻烦呢?所以,我们需要做的工作就是简化这些步骤,把它封装 在一个方法中实现. 实现: 下面给出实现代码的UML图.