访问者方式1
25.1 场景问题
25.1.1 扩展客户管理的功能
考虑这样一个应用:扩展客户管理的功能。
既然是扩展功能,那么肯定是已经存在一定的功能了,先看看已有的功能:公司的客户分成两大类,一类是企业客户,一类是个人客户,现有的功能非常简单,就是能让客户提出服务申请。目前的程序结构如图25.1所示:
图25.1 已有的客户管理程序结构示意图
现有的实现很简单,先看看Customer的实现,示例代码如下:
/** * 各种客户的父类 */ public abstract class Customer { /** * 客户编号 */ private String customerId; /** * 客户名称 */ private String name;
/** * 客户提出服务请求的方法,示意一下 */ public abstract void serviceRequest(); } |
接下来看看企业客户的实现示例代码如下:
/** * 企业客户 */ public class EnterpriseCustomer extends Customer{ /** * 联系人 */ private String linkman; /** * 联系电话 */ private String linkTelephone; /** * 企业注册地址 */ private String registerAddress;
/** * 企业客户提出服务请求的方法,示意一下 */ public void serviceRequest(){ //企业客户提出的具体服务请求 System.out.println(this.getName()+"企业提出服务请求"); } } |
再看看个人客户的实现示例代码如下:
/** * 个人客户 */ public class PersonalCustomer extends Customer{ /** * 联系电话 */ private String telephone; /** * 年龄 */ private int age; /** * 企业注册地址 */ private String registerAddress;
/** * 个人客户提出服务请求的方法,示意一下 */ public void serviceRequest(){ //个人客户提出的具体服务请求 System.out.println("客户"+this.getName()+"提出服务请求"); } } |
从上面的实现可以看出来,以前对客户的管理功能是很少的,现在随着业务的发展,需要加强对客户管理的功能,假设现在需要增加如下的功能:
- 客户对公司产品的偏好分析,针对企业客户和个人客户有不同的分析策略,主要是根据以往购买的历史、潜在购买意向等进行分析,对于企业客户还要添加上客户所在行业的发展趋势、客户的发展预期等的分析。
- 客户价值分析,针对企业客户和个人客户,有不同的分析方式和策略。主要是根据购买的金额大小、购买的产品和服务的多少、购买的频率等进行分析。
其实除了这些功能,还有很多潜在的功能,只是现在还没有要求实现,比如:针对不同的客户进行需求调查;针对不同的客户进行满意度分析;客户消费预期分析等等。虽然现在没有要求实现,但不排除今后有可能会要求实现。
25.1.2 不用模式的解决方案
要实现上面要求的功能,也不是很困难,一个很基本的想法就是:既然不同类型的客户操作是不同的,那么在不同类型的客户里面分别实现这些功能,不就可以了。
由于这些功能的实现依附于很多其它功能的实现,或者是需要很多其它的业务数据,在示例里面不太好完整的体现其功能实现,都是示意一下,因此提前说明一下。
按照上述的想法,这个时候的程序结构如图25.2所示:
图25.2 扩展客户管理功能的结构示意图
按照这个思路,把程序示意实现出来,示例如下。
(1)先看看抽象的父类,主要就是加入了两个新的方法,示例代码如下:
public abstract class Customer { private String customerId; private String name;
public abstract void serviceRequest();
/** * 客户对公司产品的偏好分析,示意一下 */ public abstract void predilectionAnalyze(); /** * 客户价值分析,示意一下 */ public abstract void worthAnalyze(); } |
(2)接下来看看企业客户的示意实现,示例代码如下:
public class EnterpriseCustomer extends Customer{ private String linkman; private String linkTelephone; private String registerAddress;
public void serviceRequest(){ //企业客户提出的具体服务请求 System.out.println(this.getName()+"企业提出服务请求"); }
/** * 企业客户对公司产品的偏好分析,示意一下 */ public void predilectionAnalyze(){ //根据过往购买的历史、潜在购买意向 //以及客户所在行业的发展趋势、客户的发展预期等的分析 System.out.println("现在对企业客户"+this.getName() +"进行产品偏好分析"); }
/** * 企业客户价值分析,示意一下 */ public void worthAnalyze(){ //根据购买的金额大小、购买的产品和服务的多少、购买的频率等进行分析 //企业客户的标准会比个人客户的高 System.out.println("现在对企业客户"+this.getName() +"进行价值分析"); } } |
(3)接下来看看个人客户的示意实现,示例代码如下:
public class PersonalCustomer extends Customer{ private String telephone; private int age;
public void serviceRequest(){ //个人客户提出的具体服务请求 System.out.println("客户"+this.getName()+"提出服务请求"); }
/** * 个人客户对公司产品的偏好分析,示意一下 */ public void predilectionAnalyze(){ System.out.println("现在对个人客户"+this.getName() +"进行产品偏好分析"); }
/** * 个人客户价值分析,示意一下 */ public void worthAnalyze(){ System.out.println("现在对个人客户"+this.getName() +"进行价值分析"); } } |
(4)如何使用上面实现的功能呢,写个客户端来测试一下,示例代码如下:
public class Client { public static void main(String[] args) { //准备点测试数据 Collection<Customer> colCustomer = preparedTestData(); //循环对客户进行操作 for(Customer cm : colCustomer){ //进行偏好分析 cm.predilectionAnalyze(); //进行价值分析 cm.worthAnalyze(); } } private static Collection<Customer> preparedTestData(){ Collection<Customer> colCustomer = new ArrayList<Customer>(); //为了测试方便,准备点数据 Customer cm1 = new EnterpriseCustomer(); cm1.setName("ABC集团"); colCustomer.add(cm1);
Customer cm2 = new EnterpriseCustomer(); cm2.setName("CDE公司"); colCustomer.add(cm2);
Customer cm3 = new PersonalCustomer(); cm3.setName("张三"); colCustomer.add(cm3);
return colCustomer; } } |
运行结果如下:
现在对企业客户ABC集团进行产品偏好分析 现在对企业客户ABC集团进行价值分析 现在对企业客户CDE公司进行产品偏好分析 现在对企业客户CDE公司进行价值分析 现在对个人客户张三进行产品偏好分析 现在对个人客户张三进行价值分析 |
25.1.3 有何问题
以很简单的方式,实现了要求的功能,这种实现有没有什么问题呢?仔细分析上面的实现,发现有两个主要的问题:
- 在企业客户和个人客户的类里面,都分别实现了提出服务请求、进行产品偏好分析、进行客户价值分析等功能,也就是说,这些功能的实现代码是混杂在同一个类里面的;而且相同的功能分散到了不同的类中去实现,这会导致整个系统难以理解、难以维护。
- 更为痛苦的是,采用这样的实现方式,如果要给客户扩展新的功能,比如前面提到的针对不同的客户进行需求调查;针对不同的客户进行满意度分析;客户消费预期分析等等。每次扩展,都需要改动企业客户的类和个人客户的类,当然也可以通过为它们扩展子类的方式,但是这样可能会造成过多的对象层次。
那么有没有办法,能够在不改变客户这个对象结构中各元素类的前提下,为这些类定义新的功能?也就是要求不改变企业客户和个人客户类,就能为企业客户和个人客户类定义新的功能?