1.定义
访问者模式一种将算法和软件结构分离的设计模式。
基本思想是:首先我们拥有一个由许多对象构成的对象结构,这些对象的类对拥有一个accept方法来接受访问者对象。访问者是一个接口,它拥有一个visit方法,这个方法对访问到的对象结构中不同类型的元素作为不同的反应。在对象结构的一次访问中,我们遍历整个对象结构,对每个元素都实施accept方法,在每个元素accept方法中回调访问者的visit方法,从而使访问者得以处理对象结构中的每一个元素。我们可以通过对对象结构设计不同的具体的访问者来完成不同的操作。
2. 类图
3. 实例
package com.jerry.designpattern; /** * * @author Jerry * @date 2015年2月10日 下午11:21:05 */ public abstract class Customer { protected String id; protected String name; public abstract void accept(Visitor visitor); public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } package com.jerry.designpattern; /** * * @author Jerry * @date 2015年2月10日 下午11:22:48 */ public class EnterpriseCustomer extends Customer{ private String linkName; private String linkPhone; private String registerAddress; @Override public void accept(Visitor visitor) { // TODO Auto-generated method stub visitor.visitEnterpriseCustomer(this); } public String getLinkName() { return linkName; } public void setLinkName(String linkName) { this.linkName = linkName; } public String getLinkPhone() { return linkPhone; } public void setLinkPhone(String linkPhone) { this.linkPhone = linkPhone; } public String getRegisterAddress() { return registerAddress; } public void setRegisterAddress(String registerAddress) { this.registerAddress = registerAddress; } } package com.jerry.designpattern; /** * * @author Jerry * @date 2015年2月10日 下午11:26:37 */ public class PersonalCustomer extends Customer{ private String phone; private int age; @Override public void accept(Visitor visitor) { // TODO Auto-generated method stub visitor.visitPersonalCustomer(this); } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } package com.jerry.designpattern; /** * * @author Jerry * @date 2015年2月10日 下午11:23:40 */ public interface Visitor { void visitPersonalCustomer(PersonalCustomer personalCustomer); void visitEnterpriseCustomer(EnterpriseCustomer enterpriseCustomer); } package com.jerry.designpattern; /** * * @author Jerry * @date 2015年2月10日 下午11:34:14 */ public class PredilectionAnalyzeVisitor implements Visitor{ @Override public void visitEnterpriseCustomer(EnterpriseCustomer enterpriseCustomer) { // TODO Auto-generated method stub System.out.println("现在对企业客户<" + enterpriseCustomer.getName() + ">进行产品偏好分析"); } public void visitPersonalCustomer(PersonalCustomer personalCustomer) { System.out.println("现在对个人客户<" + personalCustomer.getName() + ">进行产品偏好分析"); }; } package com.jerry.designpattern; /** * * @author Jerry * @date 2015年2月10日 下午11:29:54 */ public class ServiceRequestVisitor implements Visitor{ @Override public void visitPersonalCustomer(PersonalCustomer personalCustomer) { // TODO Auto-generated method stub System.out.println(personalCustomer.getName() + "提出服务请求"); } @Override public void visitEnterpriseCustomer(EnterpriseCustomer enterpriseCustomer) { // TODO Auto-generated method stub System.out.println(enterpriseCustomer.getName() + "企业提出服务请求"); } } package com.jerry.designpattern; /** * * @author Jerry * @date 2015年2月10日 下午11:38:24 */ public class Client { public static void main(String[] args) { ObjectStructure objectStructure = new ObjectStructure(); Customer c1 = new PersonalCustomer(); c1.setName("孙悟空"); objectStructure.addElement(c1); Customer c2 = new EnterpriseCustomer(); c2.setName("花果山科技有限公司"); objectStructure.addElement(c2); Customer c3 = new PersonalCustomer(); c3.setName("猪悟能"); objectStructure.addElement(c3); Customer c4 = new EnterpriseCustomer(); c4.setName("高老庄房地产集团"); objectStructure.addElement(c4); Visitor v1 = new ServiceRequestVisitor(); objectStructure.handle(v1); Visitor v2 = new PredilectionAnalyzeVisitor(); objectStructure.handle(v2); } }
4. 优缺点
访问者优点:好的扩展性、好的复用性、分离无关行为。
访问者缺点:对象结构变化很困难、破坏了对象的封装性。
5. 试用场景
以下情况下可以使用访问者呢?
如果想对一个对象结构中实施一些依赖对象结构中具体类的操作,可以使用访问者模式。
如果想对一个对象结构中进行很多不同且不相关的操作,为了避免这些操作使类变得杂乱,可以使用访问者模式,把这些操作分散到不同的访问者对象中,每个访问者实现同一类功能。
如果对象结构很少变动,但是需要经常给对象结构中的元素对象定义新的操作,可以使用访问者模式。