//訪问者模式定义:表示一个作用于某对象结构中的各个元素的操作,它使你能够在不改变各元素类的前提下定义作用于这些元素的新操作。//从定义上看。这个模式跟装饰模式的定义非常类似(动态地给一个对象加入一些额外的职责),可是装饰模式很多其它是在原有的基础上进行功能加强或者改动。而訪问者模式很多其它是为对象加入全新的功能。訪问者模式适合那些须要频繁为某些类加入新功能、新操作的项目。
//模式结构: //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); } } //client測试 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()+"进行产品偏好分析"); } } //在client的使用与请求服务方法一样 //PredilectionAnalyzeVisitor paVisitor = new PredilectionAnalyzeVisitor(); //os.handleRequest(paVisitor); //总结 //这个模式中用到了二次分发技术,跟tcp协议的三次握手有些类似。首先请求拿到对方的控制权。对方进行接受,然后開始使用控制权 //訪问者模式本质:预留通路,回调实现 //长处:扩展性好,复用性好,分离无关行为 //缺点:对象结构变化非常困难,破坏封装(被内部数据开放给了訪问者) //何时使用訪问者模式: //1.假设想对一个对象结构实施一系列依赖于对象结构中详细类的操作 //2.假设相对一个对象结构中的各个元素进行非常多不同并且不相关的操作,为了避免这些操作使类变得杂乱,能够使用 //3.假设对象结构非常少变动,可是须要常常给对象结构中的元素对象定义新的操作 //思考: //感觉能够给全部的对象都使用这个模式,这样扩展起来岂不是非常方便? //总感觉这个模式怪怪的,可能是这个样例本身的问题吧。看了下其它的样例,感觉这个样例非常不好。
还有一个样例是測试两种种子(Element)在多种不同环境下(Visitor)生长会有何不同