建造者模式(Builder Pattern):将复杂对象的创建和表示分离,使同样的构建过程可以创建不同的表示。

进一步说,建造者隐藏了产品是如何组装的,使建造代码和表示代码分离。建造对象时 构件顺序稳定 的情况下,不管每一步具体怎么变都可以适用。

简单说,建造者模式将需要一系列动作才能完成的事固化下来,并定义了一个Director给客户端使用。还是很抽象的话,想想如何把大象装进冰箱:

  1. 打开冰箱门
  2. 把大象装进去
  3. 关上冰箱门

这个步骤比较简单,但如果细化一下:买冰箱、接通电源、买大象、清洗大象……很可能就会有300个步骤。建造者模式则提供了一系列行为的集合,保证以后有把山羊装进冰箱这样的需求时候不会遗漏某个步骤(想想KFC、麦当劳生产食品的步骤,其实是建造者模式不错的例子)。

代码实现如下:

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
package main

import (
"fmt"
)

// 把xx装进冰箱
type inFridge interface {
openDoor()
putInFridge()
closeDoor()
}
type meat struct {
name string
}

func (m meat) openDoor() {
fmt.Println("Open the Door!")
}

func (m meat) closeDoor() {
fmt.Println("Close the Door!")
}

type pig struct {
meat
}
func (p pig) putInFridge() {
fmt.Printf("Put %s in fridge \n",p.name)
}

type chicken struct {
meat
}
func (c chicken) putInFridge() {
fmt.Printf("Kill the %s \n",c.name)
fmt.Printf("Put %s in fridge \n",c.name)
}

type director struct {
i inFridge
}
func (d director) createMeat() {
d.i.openDoor()
d.i.putInFridge()
d.i.closeDoor()
}


func main() {
p := pig{meat:meat{name:"pig"}}
c := chicken{meat:meat{name:"chicken"}}

d := director{i:p}
d.createMeat()

d2 := director{i:c}
d2.createMeat()
}

代码很简单,定义了meat基类和inFridge接口,并在pig以及chicken实现。把猪肉放进冰箱和把鸡肉放进冰箱步骤是一样的,而放鸡肉时候要多进行一步“杀鸡”,所以使用建造者模式时,到底将步骤抽象提取出多少步则是需要权衡的。然后客户端通过使用director来创建产品(这里我偷懒了,并没返回冻肉这个产品,而仅仅是输出),无需关心具体实现步骤,实现代码解耦。

应用场景

  1. 当生成的对象内部结构复杂时(需要很多步骤时)
  2. 需要向客户隐藏产品内部实现步骤时