设计模式(Design Patterns)- 工厂模式

写者正在学习设计模式,分享一些心得体会出来。

我所理解的设计模式就是程序员在软件开发过程中,总结出来的一种比较好的设计方法,或者说是编码技巧。多种设计模式表达了在多种特定场景下的设计方法。我会在介绍设计模式的时候,一般会给出常规方案和运用了设计模式这一技巧之后的方案。 通过比较来理解设计模式的益处。

今天我想介绍一下工厂模式

  • 开始
  • 没有运用设计模式技巧的代码
  • 运用之后的代码
  • 总结

1 开始

我不会说什么叫工厂模式,不会在这里给出一个很官方的定义。

我们先考虑一个情形,假设你在设计一款飞机大战的游戏,你希望代码给你生成不同种类的敌方飞船,那你会怎么去写代码呢?假设有一些小的飞机, 有一些大战舰,还有一些Boss级别的。

2 没有运用设计模式技巧的代码

2.1 文件 EnemyShip.java

1
2
3
4
5
6
7
8
9
10
11
12
13
package factory;
public class EnemyShip {
public EnemyShip(){}
public void sayHi() {
System.out.println("Hello, I am EnemyShip");
}
}

2.2 文件 OtherEnemyShip.java

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
package factory;
class SmallEnemyShip extends EnemyShip{
public SmallEnemyShip(){}
@Override
public void sayHi(){
System.out.println("Hello I am SmallEnemyShip");
}
// 你可以在这里来控制具体的外观和行为
}
class MiddleEnemyShip extends EnemyShip{
public MiddleEnemyShip(){}
@Override
public void sayHi(){
System.out.println("Hello I am MiddleEnemyShip");
}
// 你可以在这里来控制具体的外观和行为
}
class BigEnemyShip extends EnemyShip{
public BigEnemyShip(){}
@Override
public void sayHi(){
System.out.println("Hello I am BigEnemyShip");
}
// 你可以在这里来控制具体的外观和行为
}
class BossEnemyShip extends EnemyShip{
public BossEnemyShip(){}
@Override
public void sayHi(){
System.out.println("Hello I am BossEnemyShip");
}
// 你可以在这里来控制具体的外观和行为
}

2.3 文件 EnemyShipTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package factory;
public class EnemyShipTest{
public static void main(String[] args){
SmallEnemyShip aSmallEnemyShip = new SmallEnemyShip();
MiddleEnemyShip aMiddleEnemyShip = new MiddleEnemyShip();
BigEnemyShip aBigEnemyShip = new BigEnemyShip();
BossEnemyShip aBossEnemyShip = new BossEnemyShip();
aSmallEnemyShip.sayHi();
aMiddleEnemyShip.sayHi();
aBigEnemyShip.sayHi();
aBossEnemyShip.sayHi();
}
}

2.4 输出

1
2
3
4
Hello I am SmallEnemyShip
Hello I am MiddleEnemyShip
Hello I am BigEnemyShip
Hello I am BossEnemyShip

3 运用之后的代码

工厂模式新增加了一个工厂类,由这个类来生产具体的东西。并且在EnemyShip中添加了枚举类型Type来表示飞船的类型。

3.1 文件 EnemyShip.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package factory;
public class EnemyShip {
public enum Type {
SMALL,
MIDDLE,
BIG,
BOSS
}
public EnemyShip(){}
public void sayHi() {
System.out.println("Hello, I am EnemyShip");
}
}

3.2 文件 EnemyShipFactory.java

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
package factory;
public class EnemyShipFactory{
public EnemyShip getShip(EnemyShip.Type typeOfShip){
EnemyShip enemyShip = null;
switch (typeOfShip) {
case SMALL:
enemyShip = new SmallEnemyShip();
break;
case MIDDLE:
enemyShip = new MiddleEnemyShip();
break;
case BIG:
enemyShip = new BigEnemyShip();
break;
case BOSS:
enemyShip = new BossEnemyShip();
break;
default:
}
return enemyShip;
}
}

3.3 文件 EnemyShipTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package factory;
public class EnemyShipTest{
public static void main(String[] args){
EnemyShipFactory enemyShipFactory = new EnemyShipFactory();
EnemyShip aSmallEnemyShip = enemyShipFactory.getShip(EnemyShip.Type.SMALL);
EnemyShip aMiddleEnemyShip = enemyShipFactory.getShip(EnemyShip.Type.MIDDLE);
EnemyShip aBigEnemyShip = enemyShipFactory.getShip(EnemyShip.Type.BIG);
EnemyShip aBossEnemyShip = enemyShipFactory.getShip(EnemyShip.Type.BOSS);
aSmallEnemyShip.sayHi();
aMiddleEnemyShip.sayHi();
aBigEnemyShip.sayHi();
aBossEnemyShip.sayHi();
}
}

很显然,EnemyShipFactory是对具体的特定类型(EnemyShip的子类)创建过程的封装。对于使用来说,不需要知道怎么去创建一个想要的对象,你要做的只是告诉这个工厂需要什么东西。工厂就给你一个结果。

3.4 输出结果

1
2
3
4
Hello I am SmallEnemyShip
Hello I am MiddleEnemyShip
Hello I am BigEnemyShip
Hello I am BossEnemyShip

结果是相同的。

4 总结

工厂模式是对具体的对象创建过程的封装,在使用的时候不用去记忆类名,你可以从工厂里面拿到你想要的东西。不管是产品名(可以写在工厂类的注释里面), 还是工厂的产品。

使用者只需要记住有这么一个工厂,可以生产某种产品。在具体使用的时候,可以再去看看工厂有哪些产品。