YuHang’s Blog

设计模式(五)——工厂模式

在开发当中,会遇见有很多派生子类的情况,这时到底调用哪个子类需要程序员不断的斟酌。当需求变动时(添加或拓展功能)我们需要去每个可能选择派生子类的地方重新修改和寻找。工厂模式将为我们解决这样的烦恼。

设计原则

  1. 封装变化
    封装变化时工厂模式的核心。对于简单工厂模式,单纯由封装变化完成。
  2. 面相接口
    正是由于在代码中使用new关键字为我们带来很多的不便利性,这种不便利来源于捆绑了现实而不方便解耦和。
  3. 依赖抽象而不是依赖具体类(依赖倒置原则)
    依赖倒置原则高层依赖底层的关系改为依赖抽象。听起来是不是挺抽象的。。举个例子说明一下
    代码如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    /**
    * Created by 宇航 on 2017/2/25.
    * 为一家保险公司的设计一套线上保险推销方案
    */
    public class InsuranceCompanyTest {
    public static void main(String[] args) {
    InsuranceCompany company = new InsuranceCompany();
    company.marketingInsurance("老人");
    }
    }
    class InsuranceCompany{
    public void marketingInsurance(String typeName){
    if(typeName.equals("老人")){
    InsuranceToOlder insurance = new InsuranceToOlder();
    insurance.marketing();
    }
    }
    //其他方法如:寻找目的人群,提供售后服务
    }
    class InsuranceToOlder{
    void marketing(){
    System.out.println("祝您身体健康");
    System.out.println("给您推荐这款产品");
    }
    }

高层/底层指的是什么

高层就是指InsuranceCompany,他负责整个公司的运行逻辑。在其他项目中高层也是这些逻辑控制的部分。
底层指InsuranceToOlder,它负责某一具体产品的实现。其他项目中指某一个实现细节的功能类。

什么叫做依赖

个人理解持有相关引用即依赖,因为只要持有相关引用,一旦引用发生变化(比如删除了),高层类本身也需要改变。在本例中,如果因为某种原因对于老年人的保险取消了。那么我需要删除所有保险公司类中对于老年人保险的代码。这是非常费劲以及危险的,因为大多是情况中我们在多处进行了引用,而且类内部可能产生依赖关系,一旦删除可能马上就用不成了。

如何依赖抽象

首先你要理解为什么我们要去依赖抽象,请您先思考一下再看下一行。
因为相比起实现抽象更加的稳定。对于保险公司来说我们可能推出或者删除一个业务,但是保险我们是要一直做下去的。所以我们将各个保险业务继承自Insurance接口,在公司代码中只涉及对于接口的操作。这样无论保险怎么更改,我们公司的代码是不需要改变的——也就是说,公司类已经与具体的保险类解耦了。

##实战演练

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/**
* Created by 宇航 on 2017/2/25.
* 为一家保险公司的设计一套线上保险推销方案
* 已知以下信息:
* 1.每个都保险需要三个步骤:搜集信息,推销保险,提供售后
* 2.目前坐落于北京,上海还有一家分店,以后准备开设更多的分公司
* 3.需要针对每个城市的不同差异,我们有不同的推销方法,但是其他的部分是一样的
* 4.目前有针对老人,中年人和小孩的保险类型
* 4.受多方面的影响,我们可能随时添加或删除一个类型的保险
*/
public class InsuranceCompanyTest {
public static void main(String[] args) {
InsuranceCompany bjInsuranceCompany = new CompanyInBJ();
InsuranceCompany shInsuranceCompany = new CompanyInSH();
bjInsuranceCompany.collectInformation("老人");
bjInsuranceCompany.afterSale();
shInsuranceCompany.collectInformation("小孩");
shInsuranceCompany.afterSale();
}
}
/**
* ------------------保险和保险公司的抽象类----------------
* 提供了一个通用的接口和超类型,规定了高层业务的逻辑,即收集-销售-售后
*/
abstract class Insurance{
String type;
Integer price;
public String getType(){
return type;
}
public Integer getPrice() {
return price;
}
void display(){
System.out.println("正在准备您的基本信息"+
"类型:"+getType()+"价格:"+getPrice());
}
}
abstract class InsuranceCompany{
public void collectInformation(String type){
Insurance insurance;
System.out.println("收集顾客信息");
insurance = createInsurance(type);
insurance.display();
}
protected abstract Insurance createInsurance(String type);
public void afterSale(){
System.out.println("提供售后服务");
}
}
/**
* -------------------保险公司的具体类-----------------------
* 具体实现公司针对于不同地域的细节, 这里是工厂,针对不同的需求返回不同的对象。
*/
class CompanyInBJ extends InsuranceCompany{
@Override
protected Insurance createInsurance(String type) {
switch (type) {
case "老人":
return new BJOlderInsurance();
case "小孩":
return new BJChildInsurance();
default:
return null;
}
}
}
class CompanyInSH extends InsuranceCompany{
@Override
protected Insurance createInsurance(String type) {
switch (type){
case "老人":
return new SHOlderInsurance();
case "小孩":
return new SHChildInsurance();
default:
return null;
}
}
}
/**
* ----------------------保险的具体类-------------------------
* 规定了不同地域不同类型保险的名称,价格等细节
*/
class BJOlderInsurance extends Insurance{
public BJOlderInsurance(){
type = "北京市老人保险";
price = 240;
}
}
class BJChildInsurance extends Insurance{
public BJChildInsurance(){
type = "北京市儿童保险";
price = 260;
}
}
class SHOlderInsurance extends Insurance{
public SHOlderInsurance(){
type = "上海市老人保险";
price = 280;
}
}
class SHChildInsurance extends Insurance{
public SHChildInsurance(){
type = "上海市儿童保险";
price = 290;
}
}

运行结果:

收集顾客信息
正在准备您的基本信息类型:北京市老人保险价格:240
提供售后服务
收集顾客信息
正在准备您的基本信息类型:上海市儿童保险价格:290
提供售后服务