模式背景
考虑场景
假设现在存在一个管理系统,主要是处理客户群的系统,目前系统能够处理客户所提出的服务请求,但是随着系统业务的增加,需要为系统增加其他的功能,例如需要分析潜在客户的价值,客户对产品的偏好分析等等一系列的需求功能。对于如上的需求实现的代码如下
package com.conjane.visitorpattern;
public abstract class Customer {
private String customerId;
private String name;
public String getCustomerId() {
return customerId;
}
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void serviceRequest();
public abstract void predilectionAnalyze();
public abstract void worthAnalyze();
}
package com.conjane.visitorpattern;
public class EnterpriseCustomer extends Customer{
private String linkman;
private String linkTelephone;
private String registerAddress;
public String getLinkman() {
return linkman;
}
public void setLinkman(String linkman) {
this.linkman = linkman;
}
public String getLinkTelephone() {
return linkTelephone;
}
public void setLinkTelephone(String linkTelephone) {
this.linkTelephone = linkTelephone;
}
public String getRegisterAddress() {
return registerAddress;
}
public void setRegisterAddress(String registerAddress) {
this.registerAddress = registerAddress;
}
@Override
public void serviceRequest() {
// TODO Auto-generated method stub
System.out.println(this.getName() + "企业客户提出服务请求");
}
@Override
public void predilectionAnalyze() {
// TODO Auto-generated method stub
System.out.println(this.getName() + "企业客户购买意向分析");
}
@Override
public void worthAnalyze() {
// TODO Auto-generated method stub
System.out.println(this.getName() + "企业客户价值分析");
}
}
package com.conjane.visitorpattern;
public class PersonalCustomer extends Customer{
private String telephone;
private Integer age;
private String registerAddress;
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getRegisterAddress() {
return registerAddress;
}
public void setRegisterAddress(String registerAddress) {
this.registerAddress = registerAddress;
}
@Override
public void serviceRequest() {
// TODO Auto-generated method stub
System.out.println(this.getName() + "个人客户提出服务请求");
}
@Override
public void predilectionAnalyze() {
// TODO Auto-generated method stub
System.out.println(this.getName() + "个人客户购买意向分析");
}
@Override
public void worthAnalyze() {
// TODO Auto-generated method stub
System.out.println(this.getName() + "个人客户价值分析");
}
}
package com.conjane.visitorpattern;
import java.util.ArrayList;
import java.util.Collection;
public class Client {
private static Collection<Customer> preparedTestData(){
Collection<Customer> customers = new ArrayList<Customer>();
Customer haier = new EnterpriseCustomer();
haier.setName("海尔集团");
customers.add(haier);
Customer lianxiang = new EnterpriseCustomer();
lianxiang.setName("联想集团");
customers.add(lianxiang);
Customer personal = new PersonalCustomer();
personal.setName("张三");
customers.add(personal);
return customers;
}
public static void main(String[] args) {
Collection<Customer> customers = preparedTestData();
for(Customer customer:customers) {
customer.predilectionAnalyze();
customer.worthAnalyze();
}
}
}
上面代码利用抽象类Customer,EnterpriseCustomer和PersonalCustomer分别继承Customer实现其中的抽象方法,这是最简单的实现以上需求的方式,但是这样的实现方式是存在问题的,具体什么问题?
存在问题
- 在企业客户和个人客户的类中都是实现相同的方法,功能的实现代码是混杂在同一个类中,相同的实现方法分散在不同的类中,可能会导致系统难以理解,维护成本提高。
- 目前是存在这些个方法,但是后期还有可能添加其他的方法,每次的扩展都是修改企业客户类和个人客户类,虽然后期还可以为他们扩展子类,但是这个无疑为系统增加了额外的复杂度。
模式原理
模式定义
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
基本思路
首先定义一个借口来代表要新加入的功能,为了通用,也就是定义一个通用的功能方法来代表新加入的功能;在对象结构上添加一个方法,作为通用的功能方法,也就是可以代表被添加的功能,在这个方法中传入具体的实现新功能的对象;在对象结构的具体实现对象中实现这个方法,回调传入具体的实现新功能的对象,就相当于调用到新功能上。
模式结构
- Visitor:访问者接口,为所有的访问者对象声明一个visit方法,用来代表为对象结构添加的功能
- ConcreteVisitor:具体的访问者实现对象
- Element:抽象的元素对象
- ConcreteElement:具体元素对象
- ObjectStructure:对象结构
代码复写
package com.conjane.visitorpattern;
public interface Visitor {
public void visitEnterpriseCustomer(EnterpriseCustomer enterpriseCustomer);
public void visitPersonalCustomer(PersonalCustomer personalCustomer);
}
package com.conjane.visitorpattern;
public class ServiceRequestVisitor implements Visitor{
public void visitEnterpriseCustomer(EnterpriseCustomer enterpriseCustomer) {
// TODO Auto-generated method stub
System.out.println("企业用户进行服务请求");
}
public void visitPersonalCustomer(PersonalCustomer personalCustomer) {
// TODO Auto-generated method stub
System.out.println("个人用户进行服务请求");
}
}
package com.conjane.visitorpattern;
public class PredilectionAnalyzeVisitor implements Visitor{
public void visitEnterpriseCustomer(EnterpriseCustomer enterpriseCustomer) {
// TODO Auto-generated method stub
System.out.println("企业用户分析");
}
public void visitPersonalCustomer(PersonalCustomer personalCustomer) {
// TODO Auto-generated method stub
System.out.println("个人用户分析");
}
}
package com.conjane.visitorpattern;
public abstract class Customer {
private String customerId;
private String name;
public String getCustomerId() {
return customerId;
}
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void accept(Visitor visitor);
}
package com.conjane.visitorpattern;
public class EnterpriseCustomer extends Customer{
private String linkman;
private String linkTelephone;
private String registerAddress;
public String getLinkman() {
return linkman;
}
public void setLinkman(String linkman) {
this.linkman = linkman;
}
public String getLinkTelephone() {
return linkTelephone;
}
public void setLinkTelephone(String linkTelephone) {
this.linkTelephone = linkTelephone;
}
public String getRegisterAddress() {
return registerAddress;
}
public void setRegisterAddress(String registerAddress) {
this.registerAddress = registerAddress;
}
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
visitor.visitEnterpriseCustomer(this);
}
}
package com.conjane.visitorpattern;
public class PersonalCustomer extends Customer{
private String telephone;
private Integer age;
private String registerAddress;
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getRegisterAddress() {
return registerAddress;
}
public void setRegisterAddress(String registerAddress) {
this.registerAddress = registerAddress;
}
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
visitor.visitPersonalCustomer(this);
}
}
package com.conjane.visitorpattern;
import java.util.ArrayList;
import java.util.Collection;
public class ObjectStructure {
private Collection<Customer> customers = new ArrayList<Customer>();
public void handleRequest(Visitor visitor) {
for(Customer customer:customers) {
customer.accept(visitor);
}
}
public void addElement(Customer customer) {
this.customers.add(customer);
}
}
package com.conjane.visitorpattern;
public class Client {
public static void main(String[] args) {
ObjectStructure customers = new ObjectStructure();
Customer haier = new EnterpriseCustomer();
haier.setName("海尔集团");
customers.addElement(haier);
Customer lianxiang = new EnterpriseCustomer();
lianxiang.setName("联想集团");
customers.addElement(lianxiang);
Customer personal = new PersonalCustomer();
personal.setName("张三");
customers.addElement(personal);
ServiceRequestVisitor serviceRequestVisitor = new ServiceRequestVisitor();
customers.handleRequest(serviceRequestVisitor);
PredilectionAnalyzeVisitor predilectionAnalyzeVisitor = new PredilectionAnalyzeVisitor();
customers.handleRequest(predilectionAnalyzeVisitor);
}
}