仅供参考!
本文的源码获取:点击下载(建议使用电脑下载,解压缩后将文件夹放入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()方法执行。