设计模式之建造者模式
引入
Sunny 软件公司游戏开发小组决定开发一款网络游戏,该游戏采用RPG(Role Playing Game)模式,玩家可以在游戏中扮演虚拟世界中的一个特定角色,角色根据不同的游戏情节和统计数据(如力量、魔法、技能等)具有不同的能力,角色也会随着不断升级而拥有更强大的能力。
作为 RPG 游戏的一个重要组成部分,需要对游戏角色进行设计,而且随着该游戏的升级将不断增加新的角色。不同类型的游戏角色,其性别、脸型、服装、发型等外部特性都有所差异,
例如:
- “天使”拥有美丽的面容和披肩的长发,并身穿一袭白裙;
- “恶魔”极其丑陋,留着光头并穿一件刺眼的黑衣。
Sunny 公司决定开发一个小工具来创建游戏角色,可以创建不同类
型的角色并可以灵活增加新的角色。
Sunny 公司的开发人员通过分析发现,游戏角色是一个复杂对象,它包含性别、脸型等多个组成部分,不同的游戏角色其组成部分有所差异。但无论是何种造型的游戏角色,它的创建步骤都大同小异,都可以按照一定的流程逐步创建其组成部分,再将各组成部分装配成一个完整的游戏角色。
如何一步步创建一个包含多个组成部分的复杂对象,这是一个需要解决的问题。
其代码如下:
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 1using System;
2
3public class Actor {
4 public string Costume { get; set; }
5 public string Face { get; set;}
6 public string HairStyle { get; set; }
7 public string Sex { get; set;}
8 public string Type { get; set; }
9}
10
11public abstract class ActorBuilder {
12 protected Actor Actor = new Actor();
13 public abstract void BuildCostume();
14 public abstract void BuildFace();
15 public abstract void BuildHairStyle();
16 public abstract void BuildSex();
17 public abstract void BuildType();
18 public Actor CreateActor() {
19 return Actor;
20 }
21}
22public class ActorController{
23 public Actor Construct(ActorBuilder ab){
24 ab.BuildCostume();
25 ab.BuildFace();
26 ab.BuildHairStyle();
27 ab.BuildSex();
28 ab.BuildType();
29 return ab.CreateActor();
30 }
31}
32
33public class HeroActor : ActorBuilder
34{
35 public override void BuildType()
36 {
37 Actor.Type = "英雄";
38 }
39 public override void BuildSex()
40 {
41 Actor.Sex = "男";
42 }
43 public override void BuildFace()
44 {
45 Actor.Face = "英俊";
46 }
47 public override void BuildCostume()
48 {
49 Actor.Costume = "盔甲";
50 }
51 public override void BuildHairStyle()
52 {
53 Actor.HairStyle = "飘逸";
54 }
55}
56
57public class AngelBuilder : ActorBuilder {
58 public override void BuildType()
59 {
60 Actor.Type = "天使";
61 }
62 public override void BuildSex()
63 {
64 Actor.Sex = "女";
65 }
66 public override void BuildFace()
67 {
68 Actor.Face = "漂亮";
69 }
70 public override void BuildCostume()
71 {
72 Actor.Costume = "白裙";
73 }
74 public override void BuildHairStyle()
75 {
76 Actor.HairStyle = "披肩长发";
77 }
78}
79
80public class DevilBuilder : ActorBuilder {
81 public override void BuildType()
82 {
83 Actor.Type = "恶魔";
84 }
85 public override void BuildSex()
86 {
87 Actor.Sex = "妖";
88 }
89 public override void BuildFace()
90 {
91 Actor.Face = "丑陋";
92 }
93 public override void BuildCostume()
94 {
95 Actor.Costume = "黑衣";
96 }
97 public override void BuildHairStyle()
98 {
99 Actor.HairStyle = "光头";
100 }
101}
102
103
- 符合单一职责原则
- 符合开闭原则
建造者模式(Builder Pattern)
建造者模式:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
不同的实体创建者可以定义不同的创建过程,而且不同的实体建造者相互独立,增加新的建造者不用修改已有代码,满足”开闭原则“。
其结构如下:
-
Product 产品类:是被创建的复杂对象
-
Builder 抽象建造者类:为创建Product对象的各个部件定义抽象接口,一般有两类方法:
-
BuildPartX(),创建复杂对象的各个部件
- GetResult(),返回复杂对象
-
ConcreteBuilder 具体建造者类:复写抽象建造者类中的方法,创建一个具体Product
-
Director 指挥者类:负责安排复杂对象的创建次序,在Director的Construct()方法中按一定顺序调回建造者类的方法,完成复杂对象的创建。
Director类的高级应用
- 省略Director
将Builder与Director进行合并
如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 1public abstract class ActorBuilder
2{
3 protected Actor Actor = new Actor();
4 public abstract void BuildType();
5 public abstract void BuildSex();
6 public abstract void BuildFace();
7 public abstract void BuildCostume();
8 public abstract void BuildHairStyle();
9 public Actor Construct()
10 {
11 BuildCostume();
12 BuildFace();
13 BuildHairStyle();
14 BuildSex();
15 BuildType();
16 return Actor;
17 }
18}
19
20
这样简化了系统结构,但加重了抽象建造者的职责。
- 引入钩子方法
引入钩子方法,更精细的控制产品的创建过程。
钩子方法:
返回类型通常为bool类型,定义在抽象建造者类中
例如我们可以在游戏角色的抽象建造者类ActorBuilder 中定义
一个方法IsBareHeaded() ,用于判断某个角色是否为“光头”,
默认返回值为false 。
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 1public abstract class ActorBuilder
2{
3 protected Actor Actor = new Actor();
4 public virtual bool IsBareHeaded()
5 {
6 return false;
7 }
8 public abstract void BuildType();
9 public abstract void BuildSex();
10 public abstract void BuildFace();
11 public abstract void BuildCostume();
12 public abstract void BuildHairStyle();
13 public Actor CreateActor()
14 {
15 return Actor;
16 }
17}
18
19public class ActorController
20{
21 public Actor Construct(ActorBuilder ab)
22 {
23 ab.BuildType();
24 ab.BuildSex();
25 ab.BuildFace();
26 ab.BuildCostume();
27 if (ab.IsBareHeaded() == false)
28 {
29 ab.BuildHairStyle();
30 }
31 return ab.CreateActor();
32 }
33}
34
35
抽象工厂模式与建造者模式对比
- 抽象工厂模式返回一系列相关产品,建造者模式返回一个完整的复杂产品
- 抽象工厂模式中,客户端通过选择具体工厂来生产具体产品;建造者模式中,客户端通过选择具体建造者,通过Director类一步步创建一个复杂对象,并返回。