一、定义
在软件开发过程中有时需要创建一个复杂的对象,这个复杂对象通常由多个子部件按一定的步骤组合而成。产品都是由多个部件构成的,各个部件可以灵活选择,但其创建步骤都大同小异。将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
二、理解
其实学习每一个设计模式都不难,难的是在于找到它的应用之处,以及各种模式间的区别在什么地方,不然就会陷入一个困境 ,学完一个,忘记一个,甚至搞混掉。
建造者模式也是生成对象的模式,我们和工厂方法做对比可以发现,去除掉非核心的指挥者后,从类图关系上几乎无差异:建造者对应具体工厂,不同工厂返回不同的产品。那么差别在哪呢?从类图中也能够看到,抽象建造者中自己实现了getResult方法,而具体建造者只需关注生产各个组件即可。也就是建造者模式注重零部件的组装过程(getResult),而工厂方法模式更注重零部件的创建过程。
三、代码示例
模拟顾客(client)向销售员(指挥者)购买电脑(产品)的过程。其中脑PC由主机mainframes、显示器screen、鼠标Mouse组成,电脑具体厂家有两个。代码如下:
//建造者模式,电脑由
//包括:产品:电脑PC由主机mainframes、显示器screen、鼠标Mouse组成
//抽象建造者:电脑厂
//具体建造者:具体电脑厂家
//指挥者:导购
func main() {
//两个厂家
lenove := new(Lenove)
asus := new(Asus)
//销售
saleMan := &SaleMan{asus}
saleMan2 := &SaleMan{lenove}
fmt.Printf("info:%#v\n",saleMan.SalePC())
fmt.Printf("info:%#v",saleMan2.SalePC())
}
type SaleMan struct {
Factory IPCFactory//哪个商家的
}
func (saleMan *SaleMan) SalePC() *PC {
return saleMan.Factory.ProduceComputer()
}
type PC struct {
Mainframes string
Screen string
Mouse string
}
//着重的是在于生产不同的组件,然后组装在一起。这是和工厂模式的区分。如果不加入这些生产部分组件的 方法,和工厂模式无异
//在java中有抽象类,而golang中没有,因此,生产总
type IPCFactory interface {
ProduceComputer()*PC
ProduceMainframes()string
ProduceScreen()string
ProduceMouse()string
}
//联想
type Lenove struct {
}
func (factory *Lenove) ProduceComputer() *PC {
pc := new(PC)
pc.Mainframes = factory.ProduceMainframes()
pc.Mouse = factory.ProduceMouse()
pc.Screen = factory.ProduceScreen()
return pc
}
func (factory *Lenove) ProduceMainframes() string {
return "联想的主机"
}
func (factory *Lenove) ProduceScreen() string {
return "联想的屏幕"
}
func (factory *Lenove) ProduceMouse() string {
return "联想的鼠标"
}
//华硕
type Asus struct {
}
func (factory *Asus) ProduceComputer() *PC {
pc := new(PC)
pc.Mainframes = factory.ProduceMainframes()
pc.Mouse = factory.ProduceMouse()
pc.Screen = factory.ProduceScreen()
return pc
}
func (factory *Asus) ProduceMainframes() string {
return "华硕的主机"
}
func (factory *Asus) ProduceScreen() string {
return "华硕的屏幕"
}
func (factory *Asus) ProduceMouse() string {
return "华硕的鼠标"
}