您的位置:首页 > 其它

设计模式入门之访问者模式Visitor

2014-05-22 21:08 435 查看


//访问者模式定义:表示一个作用于某对象结构中的各个元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。
//从定义上看,这个模式跟装饰模式的定义很相似(动态地给一个对象添加一些额外的职责),但是装饰模式更多是在原有的基础上进行功能加强或者修改;而访问者模式更多是为对象添加全新的功能。访问者模式适合那些需要频繁为某些类添加新功能、新操作的项目。
//模式结构:
//Visitor:访问者接口,为所有的访问者对象声明一个visit方法,用来表示对对象结构添加的功能,理论上可以代表任意的功能
//ConcreteVisitor:具体的访问者实现对象,实现要真正被添加到对象结构中的功能
//Element:抽象的元素对象,对象结构的顶层接口,定义接受访问的操作
//ConcreteElement:具体元素对象,对象结构中具体的对象,也是被访问的对象,通常会回调访问者的真实功能,同时开放自身的数据供访问者使用
//ObjectStructure:对象结构,通常包含多个被访问的对象,它可以遍历多个被访问的对象,也可以让访问者访问它的元素
//实例:在原有基础上增加新功能
//以下是使用了访问者模式的初始代码,之后要在它的基础上进行扩展
//用户抽象类
public abstract class Customer {
private String customerId;
private String name;
//get set methods
public abstract void accept(Visitor visitor);
}
//企业客户类
public class EnterpriseCustomer extends Customer {
private String linkman;
private String linkTelephone;
private String registerAddress;
//get set methods
public void accept(Visitor visitor) {
visitor.visitEnterpriseCustomer(this);
}
}
//个人客户类
public class PersonalCustomer extends Customer {
private String telephone;
private int age;
//get set methods
public void accept(Visitor visitor) {
visitor.visitPersonalCustomer(this);
}
}
//访问者接口
public interface Visitor {
public void visitEnterpriseCustomer(EnterpriseCustomer ec);
public void visitPersonalCustomer(PersonalCustomer pc);
}
//具体的访问者,实现客户提出服务请求的功能,这个功能是模仿原有的功能,可以直接在具体类中给出
public class ServiceRequestVisitor implements Visitor {
public void visitEnterpriseCustomer(EnterpriseCustomer ec) {
// 拿到了企业用户对象的数据
System.out.prinln(ec.getName()+"企业提出服务请求");
}
public void visitPersonalCustomer(PersonalCustomer pc) {
// 拿到了个人用户对象的数据
System.out.prinln(pc.getName()+"提出服务请求");
}
}
//ObjectStructure
public class ObjectStructure {
private Collection<Customer> col = new ArrayList<Customer>();
public void handleRequest(Visitor visitor) {
for(Customer cm : col) {
cm.accept(visitor);
}
}
public void addElement(Customer ele) {
this.col.add(ele);
}
}
//客户端测试
public class Client {
public static void main(String[] args) {
ObjectStructure os = new ObjectStructure();
Customer cm1 = new EnterpriseCustomer();
cm1.setName("ABC集团");
os.addElement(cm1);//加入到os中,以增加新功能
Customer cm2 = new EnterpriseCustomer();
cm2.setName("CDE公司");
os.addElement(cm2);
Customer cm3 = new PersonalCustomer();
cm3.setName("张三");
os.addElement(cm3);

ServiceRequestVisitor srVisitor = new ServiceRequestVisitor();
os.handleRequest(srVisitor);
}
}
//下面对现在的功能做扩展,增加一个对客户进行偏好分析的功能,只需要增加一个具体的访问者就行了
public class PredilectionAnalyzeVisitor implements Visitor {
public void visitEnterpriseCustomer(EnterpriseCustomer ec) {
// 拿到了企业用户对象的数据
System.out.prinln("现在对企业客户-"+ec.getName()+"进行产品偏好分析");
}
public void visitPersonalCustomer(PersonalCustomer pc) {
// 拿到了个人用户对象的数据
System.out.prinln("现在对个人客户-"+pc.getName()+"进行产品偏好分析");
}
}
//在客户端的使用与请求服务方法一样
//PredilectionAnalyzeVisitor paVisitor = new PredilectionAnalyzeVisitor();
//os.handleRequest(paVisitor);

//总结
//这个模式中用到了二次分发技术,跟tcp协议的三次握手有些类似,首先请求拿到对方的控制权,对方进行接受,然后开始使用控制权
//访问者模式本质:预留通路,回调实现
//优点:扩展性好,复用性好,分离无关行为
//缺点:对象结构变化很困难,破坏封装(被内部数据开放给了访问者)
//何时使用访问者模式:
//1.如果想对一个对象结构实施一系列依赖于对象结构中具体类的操作
//2.如果相对一个对象结构中的各个元素进行很多不同而且不相关的操作,为了避免这些操作使类变得杂乱,可以使用
//3.如果对象结构很少变动,但是需要经常给对象结构中的元素对象定义新的操作
//思考:
//感觉可以给所有的对象都使用这个模式,这样扩展起来岂不是很方便?
//总感觉这个模式怪怪的,可能是这个例子本身的问题吧,看了下其他的例子,感觉这个例子很不好。另一个例子是测试两种种子(Element)在多种不同环境下(Visitor)生长会有何不同
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息