设计模式——访问者(Visitor Pattern)

一、访问者模式的定义:

访问者模式:封装一些施加于某对象数据结构上的元素的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。为相同类型的数据结构提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式,这就是访问者模式的模式动机。


二、访问者模式的构成:


访问者模式的类图

1、Visistor:为每个Element的类声明一个访问操作。某个操作专门对应某个Element类。

2、ConcreteVisitor:实现Visitor声明的操作,某种具体的实现对应具体的目的,ConcreteVisitor1和ConcreteVisitor2有不同的目的。

3、Element:定一些基本的方法,如数据的get与set方法,和接收者方法accept(Visitor v)。

4、ElementA(或ElementB):具体的Element的子类,该类必须有父类的接收者方法accept(Visitor v)和一些非必须的辅助操作Operation()。


三、访问者模式的应用场景:

1、当有多中不相干的运算对用在这些对象上,而且用户不希望混淆这些类时,可以使用访问者模式将这些运算封装到独立的类中。

2、在对象的数据类型很少变化,但需要经常改变操作或者新增加新的操作的情况下,可以使用的访问者模式。

3、当一个对象的结构中,包含有多种类型的具有不同接口的对象,且用户要在这些对象上进行依赖于具体的类的运算时,需要用到访问者模式。


四、访问者模式的有缺点:

优点:

1、在添加新的计算方法时,只需在访问者类中加上该新方法即可。

2、将相同计算效果的方法集中到某一个具体访问者类中,将其他相同的效果的计算方法集中到另外具体的访问者类中。即访问者模式很方便的将不同计算效果的方法分类归纳到某个具体的访问者子类中。

优点:

当增加一个新的Element的子类时,需要改动访问者模式的Visitor接口来添加新的计算方法,进而改动所有的ConcreteVisitor类。即改动代价太高


五、访问者模式的应用举例

某名牌汽车专公司,汽车的系列很少变化,如家用型HomeCar、商用型BusinessCar和跑车型RunningCar等。每种类型的汽车有不同的价格和不同的信息介绍,现在需要设计一种专卖店供货软件,需要计算出供应的车子的价格和车子的信息。本例可以采用访问者模式,代码实现如下:

//汽车接口 声明公用方法
public interface Car {
	float getPrice();
	String getInfo();
	void accept(CarVisitor cv);
}

//具体的汽车类  HomeCar
public class HomeCar implements Car {
	
	private float price;
	private String info;
	
	public HomeCar(){
		this.price = 550000;
		this.info = "家用车信息………………";
	}

	@Override
	public float getPrice() {
		return this.price;
	}

	@Override
	public String getInfo() {
		return this.info;
	}

	@Override
	public void accept(CarVisitor cv) {
		System.out.println("HomeCar 已经被访问了");
		cv.visitHomeCar(this);
	}

}

//具体的汽车类  BusinessCar
public class BusinessCar implements Car {

	private float price;
	private String info;
	
	public BusinessCar(){
		this.price = 950000;
		this.info = "商用车信息………………";
	}

	@Override
	public float getPrice() {
		return this.price;
	}

	@Override
	public String getInfo() {
		return this.info;
	}

	@Override
	public void accept(CarVisitor cv) {
		System.out.println("BusinessCar 已经被访问了");
		cv.visitBusinessCar(this);
	}

}

//具体的汽车类  RunningCar
public class RunningCar implements Car {
	private float price;
	private String info;
	
	public RunningCar(){
		this.price = 1750000;
		this.info = "跑车信息………………";
	}

	@Override
	public float getPrice() {
		return this.price;
	}

	@Override
	public String getInfo() {
		return this.info;
	}

	@Override
	public void accept(CarVisitor cv) {
		System.out.println("RunningCar 已经被访问了");
		cv.visitRunningCar(this);
	}

}

/**
 * Visitor接口声明操作接口
 * @author 矢的丶飞跃
 *
 */
public interface CarVisitor {
	void visitHomeCar(HomeCar hc);
	void visitBusinessCar(BusinessCar bc);
	void visitRunningCar(RunningCar rc);
}

//汽车的信息访问者类
public class CarInfoVisitor implements CarVisitor {

	@Override
	public void visitHomeCar(HomeCar hc) {
		System.out.println(hc.getInfo());
	}

	@Override
	public void visitBusinessCar(BusinessCar bc) {
		System.out.println(bc.getInfo());
	}

	@Override
	public void visitRunningCar(RunningCar rc) {
		System.out.println(rc.getInfo());
	}

}

//汽车的价格访问者类
public class CarPriceVisitor implements CarVisitor {

	private float totalPrice;
	
	public CarPriceVisitor() {
		this.totalPrice = 0;
	}

	@Override
	public void visitHomeCar(HomeCar hc) {
		this.totalPrice += hc.getPrice();
	}

	@Override
	public void visitBusinessCar(BusinessCar bc) {
		this.totalPrice += bc.getPrice();
	}

	@Override
	public void visitRunningCar(RunningCar rc) {
		this.totalPrice += rc.getPrice();
	}
	
	public float getTotalPrice(){
		return this.totalPrice;
	}

}

运行结果:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值