设计模式:02-工厂模式

1、简单工厂模式

1.1 看一个具体的需求

看一个披萨的项目:要便于披萨种类的扩展,要便于维护

1)披萨的种类很多(比如 GreekPizza、CheesePizza 等)

2)披萨的制作有 prepare,bake,cut,box

3)完成披萨店订购功能

1.2 使用传统的方式来完成

1)思路分析(类图)

d89xn

2)代码演示

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
public abstract class Pizza {  
/**
* 名字
*/
protected String name;
/**
* 准备原材料,不同的披萨不一样,因此,我们做成抽象方法
*/
public abstract void prepare();
/**
* 烘烤
*/
public void bake() {
System.out.println(name + " baking; ");
}
/**
* 切割
*/
public void cut() {
System.out.println(name + " cutting; ");
}
/**
* 打包
*/
public void box() {
System.out.println(name + " boxing; ");
}
public void setName(final String name) {
this.name = name;
}
}

public class CheesePizza extends Pizza{
@Override
public void prepare() {
System.out.println("给制作奶酪披萨准备原材料");
}
}

public class GreekPizza extends Pizza{
@Override
public void prepare() {
System.out.println("给制作希腊披萨准备原材料");
}
}

public class OrderPizza {
/**
* 构造器
*/
public OrderPizza() {
Pizza pizza = null;
// 订购披萨的类型
String orderType;

do {
orderType = getType();
if ("greek".equals(orderType)) {
pizza = new GreekPizza();
pizza.setName("希腊披萨");
} else if ("cheese".equals(orderType)) {
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
} else {
break;
}
// 输出披萨制作过程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}

/**
* 可以获取客户希望订购的披萨种类
*/
private String getType() {
try {
final BufferedReader strIn = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza type: ");
final String str = strIn.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}

public class PizzaStore {
public static void main(String[] args) {
new OrderPizza();
}
}

1.3 传统的方式的优缺点

1)优点是比较好理解,简单易操作。

2)缺点是违反了设计模式的 OCP 原则,即对扩展开发,对修改关闭。即当我们给类增加新功能的时候,尽量不修改代码,或者尽可能少修改代码。

3)比如我们这时要新增加一个 Pizza 的种类(Pepper 披萨),我们需要做如下修改。

  • 新增 PeeperPizza 类
  • 在 OrderPizza 中新增 else-if 判断
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
public class PepperPizza extends Pizza {  
@Override
public void prepare() {
System.out.println("给制作胡椒披萨准备原材料");
}
}

public class OrderPizza {
/**
* 构造器
*/
public OrderPizza() {
Pizza pizza = null;
// 订购披萨的类型
String orderType;

do {
orderType = getType();
if ("greek".equals(orderType)) {
pizza = new GreekPizza();
pizza.setName("希腊披萨");
} else if ("cheese".equals(orderType)) {
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
} else if ("pepper".equals(orderType)) {
pizza = new PepperPizza();
pizza.setName("胡椒披萨");
} else {
break;
}
// 输出披萨制作过程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}

/**
* 可以获取客户希望订购的披萨种类
*/
private String getType() {
try {
final BufferedReader strIn = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza type: ");
final String str = strIn.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}

4)改进的思路分析

分析:修改代码可以接受,但是如果我们在其他的地方也有创建 Pizza 的代码,就意味着,也需要修改,而创建 Pizza 的代码,往往有多处。

思路:把创建 Pizza 对象封装到一个类中,这样我们有新的 Pizza 种类时,只需要修改该类即可,其他有创建到 Pizza 对象的代码就不需要修改了。-> 简单工厂模式

1.4 基本介绍

1)简单工厂模式是属于创建型模式,也叫做静态工厂模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建处哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式。

2)简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)。

3)在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式。

1.5 使用简单工厂模式

1)简单工厂模式的设计方案:定义一个可以实例化 Pizza 对象的类,封装创建对象的代码。

2)代码示例:

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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
public abstract class Pizza {  
protected String name;

public abstract void prepare();

public void bake() {
System.out.println(name + " baking; ");
}

public void cut() {
System.out.println(name + " cutting; ");
}

public void box() {
System.out.println(name + " boxing; ");
}

public void setName(final String name) {
this.name = name;
}
}

public class CheesePizza extends Pizza{
@Override
public void prepare() {
System.out.println("给制作奶酪披萨准备原材料");
}
}

public class GreekPizza extends Pizza{
@Override
public void prepare() {
System.out.println("给制作希腊披萨准备原材料");
}
}

public class PepperPizza extends Pizza{
@Override
public void prepare() {
System.out.println("给制作胡椒披萨准备原材料");
}
}

public class SimpleFactory {
public Pizza createPizza(String orderType) {
Pizza pizza = null;
if ("greek".equals(orderType)) {
pizza = new GreekPizza();
pizza.setName("希腊披萨");
} else if ("cheese".equals(orderType)) {
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
} else if ("pepper".equals(orderType)) {
pizza = new PepperPizza();
pizza.setName("胡椒披萨");
}
return pizza;
}

public static Pizza createPizza2(String orderType) {
Pizza pizza = null;
if ("greek".equals(orderType)) {
pizza = new GreekPizza();
pizza.setName("希腊披萨");
} else if ("cheese".equals(orderType)) {
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
} else if ("pepper".equals(orderType)) {
pizza = new PepperPizza();
pizza.setName("胡椒披萨");
}
return pizza;
}
}

public class OrderPizza {

// 定义一个简单工厂对象
SimpleFactory simpleFactory;
Pizza pizza = null;

public OrderPizza(SimpleFactory simpleFactory) {
setSimpleFactory(simpleFactory);
}

public void setSimpleFactory(final SimpleFactory simpleFactory) {
this.simpleFactory = simpleFactory;

String orderType = "";

do {
orderType = getType();
pizza = this.simpleFactory.createPizza(orderType);
// 输出pizza
if (pizza != null) {
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println("订购披萨失败");
break;
}
} while (true);
}

/**
* 获取披萨类型
*
* @return
*/
private String getType() {
try {
final BufferedReader strIn = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza type: ");
final String str = strIn.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}

public class OrderPizza2 {

Pizza pizza = null;
String orderType = "";

public OrderPizza2() {
do {
orderType = getType();
pizza = SimpleFactory.createPizza2(orderType);
// 输出pizza
if (pizza != null) {
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println("订购披萨失败");
break;
}
} while (true);
}

private String getType() {
try {
final BufferedReader strIn = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza type: ");
final String str = strIn.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}

public class PizzaStore {
public static void main(String[] args) {
// 使用简单工厂模式
// new OrderPizza(new SimpleFactory());

// 静态工厂模式
new OrderPizza2();
}
}

2、工厂方法模式

2.1 看一个新的需求

披萨项目新的需求:客户在点披萨时,可以点不同口味的披萨,比如 北京的奶酪pizza、北京的胡椒 pizza 或者是伦敦的奶酪 pizza、伦敦的胡椒 pizza。

2.2 思路 1

使用简单工厂模式,创建不同的简单工厂类,比如 BJPizzaSimpleFactory、LDPizzaSimpleFactory 等等,从当前这个案例来说,也是可以的,但是考虑到项目的规模,以及软件的可维护性、可扩展性并不是特别好。

2.3 思路 2

使用工厂方法模式

2.3 工厂方法模式介绍

工厂方法模式设计方案:将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现。

工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类

2.4 工厂方法模式应用案例

1)思路分析图解

13s7q

2)代码实现:

Pizza抽象类

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
package com.wenze.design.factory.factoryMethod.pizzaStore.pizza;  

/**
* 披萨抽象类
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 10:39:55
* @since 1.0
*/
public abstract class Pizza {
protected String name;
public void setName(final String name) {
this.name = name;
}
public abstract void prepare();
public void bake() {
System.out.println(name + " baking; ");
}
public void cut() {
System.out.println(name + " cutting; ");
}
public void box() {
System.out.println(name + " boxing; ");
}
}

BJCheesePizza 北京奶酪披萨类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.wenze.design.factory.factoryMethod.pizzaStore.pizza;  

/**
* 北京奶酪披萨类
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 10:41:01
* @since 1.0
*/
public class BJCheesePizza extends Pizza{
@Override
public void prepare() {
setName("北京奶酪披萨");
System.out.println("给制作北京奶酪披萨准备原材料");
}
}

BJPepperPizza 北京胡椒披萨类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.wenze.design.factory.factoryMethod.pizzaStore.pizza;  

/**
* 北京胡椒披萨
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 10:41:21
* @since 1.0
*/
public class BJPepperPizza extends Pizza{
@Override
public void prepare() {
setName("北京胡椒披萨");
System.out.println("给制作北京胡椒披萨准备原材料");
}
}

LDCheesePizza 伦敦奶酪披萨类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.wenze.design.factory.factoryMethod.pizzaStore.pizza;  

/**
* 伦敦奶酪披萨
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 10:41:40
* @since 1.0
*/
public class LDCheesePizza extends Pizza{
@Override
public void prepare() {
setName("伦敦奶酪披萨");
System.out.println("给制作伦敦奶酪披萨准备原材料");
}
}

LDPepperPizza 伦敦胡椒披萨类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.wenze.design.factory.factoryMethod.pizzaStore.pizza;  

/**
* 伦敦胡椒披萨
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 10:42:01
* @since 1.0
*/
public class LDPepperPizza extends Pizza{
@Override
public void prepare() {
setName("伦敦胡椒披萨");
System.out.println("给制作伦敦胡椒披萨准备原材料");
}
}

OrderPizza 披萨订购抽象类

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
package com.wenze.design.factory.factoryMethod.pizzaStore.order;  


import com.wenze.design.factory.factoryMethod.pizzaStore.pizza.Pizza;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
* 订购披萨的抽象类
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 10:43:08
* @since 1.0
*/
public abstract class OrderPizza {

/**
* 订购披萨的抽象方法
*
* @param orderType 订购披萨的类型
* @return 披萨
*/
public abstract Pizza createPizza(String orderType);

/**
* 构造器
*/
public OrderPizza() {
Pizza pizza = null;
String orderType;
do {
orderType = getType();
pizza = createPizza(orderType);
if (null != pizza) {
//输出pizza制作过程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println("订购披萨失败");
break;
}
} while (true);
}

/**
* 获取客户希望订购的披萨种类
*
* @return 披萨种类
*/
private String getType() {
try {
final BufferedReader strIn = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza type: ");
final String str = strIn.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}

BJOrderPizza 北京披萨订购抽象类

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
package com.wenze.design.factory.factoryMethod.pizzaStore.order;  

import com.wenze.design.factory.factoryMethod.pizzaStore.pizza.BJCheesePizza;
import com.wenze.design.factory.factoryMethod.pizzaStore.pizza.BJPepperPizza;
import com.wenze.design.factory.factoryMethod.pizzaStore.pizza.Pizza;

/**
* 北京披萨订购类
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 10:46:07
* @since 1.0
*/
public class BJOrderPizza extends OrderPizza {

/**
* 订购披萨的抽象方法
*
* @param orderType 订购披萨的类型
* @return 披萨
*/
@Override
public Pizza createPizza(final String orderType) {
return switch (orderType) {
case "BJ-cheese" -> new BJCheesePizza();
case "BJ-pepper" -> new BJPepperPizza();
default -> null;
};
}
}

LDOrderPizza 伦敦披萨订购抽象类

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
package com.wenze.design.factory.factoryMethod.pizzaStore.order;  

import com.wenze.design.factory.factoryMethod.pizzaStore.pizza.LDCheesePizza;
import com.wenze.design.factory.factoryMethod.pizzaStore.pizza.LDPepperPizza;
import com.wenze.design.factory.factoryMethod.pizzaStore.pizza.Pizza;

/**
* 伦敦披萨订购类
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 10:48:04
* @since 1.0
*/
public class LDOrderPizza extends OrderPizza{
/**
* 订购披萨的抽象方法
*
* @param orderType 订购披萨的类型
* @return 披萨
*/
@Override
public Pizza createPizza(final String orderType) {
return switch (orderType) {
case "LD-cheese" -> new LDCheesePizza();
case "LD-pepper" -> new LDPepperPizza();
default -> null;
};
}
}

PizzaStore 披萨订购入口

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
package com.wenze.design.factory.factoryMethod.pizzaStore.order;  

/**
* 披萨店
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 10:50:38
* @since 1.0
*/
public class PizzaStore {
public static void main(String[] args) {
// 订购北京披萨
new BJOrderPizza();
// 订购伦敦披萨
new LDOrderPizza();
// 若想一次性调用北京或伦敦披萨
// 目前可以先通过输入判断想要哪个地区的披萨 %%,然后再调用相应的披萨类
String location = "BJ"; // 控制台获取数据
switch (location) {
case "BJ" -> new BJOrderPizza();
case "LD" -> new LDOrderPizza();
default -> {}
}
}
}

3、抽象工厂模式

3.1 基本介绍

1)抽象工厂模式:定义了一个 interface 用于创建相关或有依赖关系的对象簇,而无需指明具体的类。

2)抽象工厂模式可以将简单工厂模式工厂方法模式进行整合。

3)从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。

4)将工厂抽象成两层,AbsFactory(抽象工厂)和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。

3.2 抽象工厂模式应用实例

使用抽象工厂模式完成披萨项目

类图:
c0abs

代码实现:

Pizza 披萨类

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
package com.wenze.design.factory.abstractFactory.pizzaStore.pizza;  

/**
* 披萨抽象类
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 11:41:59
* @since 1.0
*/
public abstract class Pizza {
protected String name;
public void setName(final String name) {
this.name = name;
}
public abstract void prepare();
public void bake() {
System.out.println(name + " baking; ");
}
public void cut() {
System.out.println(name + " cutting; ");
}
public void box() {
System.out.println(name + " boxing; ");
}
}

BJCheesePizza 北京奶酪披萨

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.wenze.design.factory.abstractFactory.pizzaStore.pizza;  

/**
* 北京奶酪披萨
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 11:42:45
* @since 1.0
*/
public class BJCheesePizza extends Pizza{
@Override
public void prepare() {
setName("北京奶酪披萨");
System.out.println("给制作北京奶酪披萨准备原材料");
}
}

BJPepperPizza 北京胡椒披萨

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.wenze.design.factory.abstractFactory.pizzaStore.pizza;  

/**
* 北京胡椒披萨
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 11:43:06
* @since 1.0
*/
public class BJPepperPizza extends Pizza {
@Override
public void prepare() {
setName("北京胡椒披萨");
System.out.println("给制作北京胡椒披萨准备原材料");
}
}

LDCheesePizza 伦敦奶酪披萨

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.wenze.design.factory.abstractFactory.pizzaStore.pizza;  

/**
* 伦敦奶酪披萨
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 11:43:27
* @since 1.0
*/
public class LDCheesePizza extends Pizza {
@Override
public void prepare() {
setName("伦敦奶酪披萨");
System.out.println("给制作伦敦奶酪披萨准备原材料");
}
}

LDPepperPizza 伦敦胡椒披萨

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.wenze.design.factory.abstractFactory.pizzaStore.pizza;  

/**
* 伦敦胡椒披萨
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 11:43:48
* @since 1.0
*/
public class LDPepperPizza extends Pizza {
@Override
public void prepare() {
setName("伦敦胡椒披萨");
System.out.println("给制作伦敦胡椒披萨准备原材料");
}
}

AbstractFactory 抽象工厂接口

1
2
3
4
5
6
7
8
9
10
11
/**  
* 抽象工厂接口
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 11:44:17
* @since 1.0
*/
public interface AbstractFactory {
Pizza createPizza(String orderType);
}

BJFactory 北京披萨工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.wenze.design.factory.abstractFactory.pizzaStore.order;  

import com.wenze.design.factory.abstractFactory.pizzaStore.pizza.BJCheesePizza;
import com.wenze.design.factory.abstractFactory.pizzaStore.pizza.BJPepperPizza;
import com.wenze.design.factory.abstractFactory.pizzaStore.pizza.Pizza;

/**
* 北京披萨工厂
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 11:45:12
* @since 1.0
*/
public class BJFactory implements AbstractFactory{
@Override
public Pizza createPizza(final String orderType) {
return switch (orderType) {
case "cheese" -> new BJCheesePizza();
case "pepper" -> new BJPepperPizza();
default -> null;
};
}
}

LDFactory 伦敦披萨工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.wenze.design.factory.abstractFactory.pizzaStore.order;  

import com.wenze.design.factory.abstractFactory.pizzaStore.pizza.LDCheesePizza;
import com.wenze.design.factory.abstractFactory.pizzaStore.pizza.LDPepperPizza;
import com.wenze.design.factory.abstractFactory.pizzaStore.pizza.Pizza;

/**
* 伦敦披萨工厂
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 11:46:14
* @since 1.0
*/
public class LDFactory implements AbstractFactory {
@Override
public Pizza createPizza(final String orderType) {
return switch (orderType) {
case "cheese" -> new LDCheesePizza();
case "pepper" -> new LDPepperPizza();
default -> null;
};
}
}

OrderPizza 披萨订购类

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
package com.wenze.design.factory.abstractFactory.pizzaStore.order;  

import com.wenze.design.factory.abstractFactory.pizzaStore.pizza.Pizza;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
* 订购披萨类
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 11:47:06
* @since 1.0
*/
public class OrderPizza {

private AbstractFactory factory;

public OrderPizza(AbstractFactory factory) {
setFactory(factory);
}

private void setFactory(AbstractFactory factory) {
Pizza pizza;
String orderType;
this.factory = factory;

do {
orderType = getType();
pizza = this.factory.createPizza(orderType);
if (pizza != null) {
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println("订购披萨失败");
break;
}
} while (true);
}

/**
* 获取客户希望订购的披萨种类
*
* @return 披萨种类
*/
private String getType() {
try {
final BufferedReader strIn = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza type: ");
final String str = strIn.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}

PizzaStore 披萨客户端类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.wenze.design.factory.abstractFactory.pizzaStore.order;  

/**
* 披萨店
*
* @author wenze
* @version 1.0
* @Date 2023-10-19 11:51:03
* @since 1.0
*/
public class PizzaStore {
public static void main(String[] args) {
//创建北京口味的各种披萨
new OrderPizza(new BJFactory());
//创建伦敦口味的各种披萨
new OrderPizza(new LDFactory());
}
}

4、工厂模式在 JDK 应用的源码分析

1)JDK 中的 Calendar 类中,就使用了简单工厂模式

2)源码分析 + Debug 源码 + 说明

creareCalendar() 方法

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
private static Calendar createCalendar(TimeZone zone, Locale aLocale){  
CalendarProvider provider =
LocaleProviderAdapter.getAdapter(CalendarProvider.class,aLocale)
.getCalendarProvider();
if (provider != null) {
try {
return provider.getInstance(zone, aLocale);
} catch (IllegalArgumentException iae) {
// fall back to the default instantiation
}
}
Calendar cal = null;

if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
cal = switch (caltype) {
case "buddhist" -> new BuddhistCalendar(zone, aLocale);
case "japanese" -> new JapaneseImperialCalendar(zone, aLocale);
case "gregory" -> new GregorianCalendar(zone, aLocale);
default -> null;
};
}
}
if (cal == null) {
cal = new BuddhistCalendar(zone, aLocale);
} else if (aLocale.getVariant() == "JP"
&& aLocale.getLanguage() == "ja"
&& aLocale.getCountry() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
return cal;
}

5、工厂模式小结

5.1 工厂模式的意义

将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。

5.2 三种工厂模式

1)简单工厂模式

2)工厂方法模式

3)抽象工厂模式

5.3 设计模式的依赖抽象原则

1)创建对象实例时,不要直接 new 类,而是把这个 new 类的动作放在一个工厂的方法中,并返回。有的书上说,变量不要直接持有具体类的引用。

2)不要让类继承具体类,而是继承抽象类或者是实现 interface(接口)

3)不要覆盖基类中已经实现的方法。