设计模式之访问者模式(Visitor)

仅供参考!

本文的源码获取:点击下载(建议使用电脑下载,解压缩后将文件夹放入src即可)

一、访问者模式的定义

访问者模式是对象的行为模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。

二、访问者模式的结构图

在这个图中重点关注三个类,一个是被访问者(Element),一个是访问者(Visitor),还有一个是ObjectStructure(被访问者集合)。

解析一下流程:

1.被访问者(Element)有一个接收访问者(Visitor)的方法(accept),这个方法的参数是Visitor.

2.Visitor里面有一个访问的方法(vistorConcreateElement)参数是Element

3.这时候可以通过accept方法将访问者(visitor)传入,然后调用visitor的visitorConcreateElement的方法(用this参数),将被访问者(Element)传入到访问者(Visitor)中,然后在Visitor中完成相应的操作。

这里要好好体会一下,accept方法和visitor方法,这两个方法是形成一个通路的,调用的方法也是十分巧妙的。

ObjectStructure类也是一个重点,里面包含了一个List<Element>(一个被访问者集合),作用是,通过循环调用List<Element>里面的Element的accept方法完成操作【需要传入一个访问者Visitor】。

三、对定义的体会

定义:访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。

理解句子一:

封装一些施加于某种数据结构元素之上的操作

某种数据结构元素:指的是被访问者(Element)

操作:指的是Visitor的visit方法。

理解句子二:

一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。

为什么说这个操作的数据结构可以不变?这个数据结构指的是被访问者(Element),不变的原因:这个操作已经提取出来放入Visitor中,所以只要改变Visitor即可。而Element是不用改变的。

四、具体案例

场景:有一个Visitor,需要给访问顾客,顾客分为普通顾客:CommonCustomer和特殊用户SpecialCustomer。

代码清单1:

定义Visitor接口,并且定义两个方法,visitCommonCustomer()和visitSpecialCustomer()代码如下:

[CommonCustomer类、SpecialCustomer类后面有代码]

package visitor;

/**访问者Visitor*/
public interface Visitor {
	
	/**访问普通用户*/
	public void visitCommonCustomer(CommonCustomer commonCustomer);
	
	/**访问特殊用户*/
	public void visitSpecialCustomer(SpecialCustomer specialCustomer);
}

代码清单2:

定义抽象类Customer类,并且定义接收访问者的方法,visit();

代码如下:

package visitor;

/**被访问者 Customer*/
public abstract class Customer {
	
	/**accept方法接受访问者Visitor*/
	public abstract  void accept(Visitor visitor);

}

代码清单3:

定义RequestVisitor实现Visitor接口,并实现定义的两个方法,用来操作对应的顾客,代码如下:

package visitor;

/**请求访问者RequestVisitor*/
public class RequestVisitor implements Visitor{

	@Override
	public void visitCommonCustomer(CommonCustomer commonCustomer) {
		System.out.println("正在 visit CommonCustomer");
	}

	@Override
	public void visitSpecialCustomer(SpecialCustomer specialCustomer) {
		System.out.println("正在 visit SpecialCustomer");
	}

}
代码清单4:

定义CommonCustomer,继承Customer类,并实现accept方法。代码如下:

package visitor;

/*普通顾客**/
public class CommonCustomer extends Customer{

	@Override
	public void accept(Visitor visitor) {
		
		/**调用Visitor的访问普通顾客方法*/
		visitor.visitCommonCustomer(this);
	}

}

定义SpecialCustomer,继承Customer类,并实现accept方法。代码如下:

package visitor;

/**特殊顾客*/
public class SpecialCustomer extends Customer{

	@Override
	public void accept(Visitor visitor) {
		
		/**调用Visitor的访问特殊顾客方法*/
		visitor.visitSpecialCustomer(this);
	}

}

代码清单5:

定义ObjectStructure,里面包含List<Customer> ,通过doRequest()方法,使得List里面的Customer均调用accept方法。

代码如下:

package visitor;

import java.util.ArrayList;
import java.util.List;

public class ObjectStructure {
	
	private List<Customer> listCustomers=new ArrayList<Customer>();
	
	public void addCustomer(Customer customer){
		listCustomers.add(customer);
	}
	
	public void doRequest(Visitor visitor){
		for (Customer customer : listCustomers) {
			customer.accept(visitor);
		}
	}

}

代码清单6:

Main函数模拟流程,代码如下:

package visitor;

public class Main {

	public static void main(String[] args) {
		//准备Visitor
		Visitor requestVisitor=new RequestVisitor();
		//准备被访问者
		Customer commonCustomer=new CommonCustomer();
		Customer specialCustomer=new SpecialCustomer();
		//准备ObjectStructure
		ObjectStructure objectStructure=new ObjectStructure();
		objectStructure.addCustomer(commonCustomer);
		objectStructure.addCustomer(specialCustomer);
		//通过ObjectStructure让所有Customer接受Visitor的访问
		objectStructure.doRequest(requestVisitor);
		//.....可以创建更多的Visitor

	}

}

流程解析:

Main类准备Customer、Visitor和ObjectStructure类中的List<Customer>的数据==》调用ObjectStructure的doRequest方法==》doRequest方法会接收一个Visitor==》doRequest方法循环List<Element>,并调用每一个Element的accept方法。==》accpet方法里面调用visitor的visit()方法==》最后所有操作在Visitor类的visit()方法执行。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值