Go 代码示例
代码组织结构如下:
- 首先创建
house.go
文件, 建立House
这个产品基类,代码如下;
package main type House struct { windowType string doorType string swimPool string floor int }
正像前文所说一眼,房子有窗户、门、游泳池、楼层等部分组成。
- 然后创建抽象创建者
iBuilder.go
文件,也是我们的建造者接口,分别定义 4 个set
和 1 个getHouse()
方法,代码如下:
package main type IBuilder interface { setWindowType() setDoorType() setNumFloor() setSwimPool() getHouse() House } func getBuilder(builderType string) IBuilder { if builderType == "normal" { return newNormalBuilder() } if builderType == "cottages" { return newCottagesBuilder() } return nil }
- 新建具体建造者:普通房子
normalBuilder.go
,在这个文件中,因为 Go 语言没有继承的概念,所以也需要我们定义跟House
相同的结构体,然后实现 normalHouse 的构建 :
package main type NormalBuilder struct { windowType string doorType string swimPool string floor int } func newNormalBuilder() *NormalBuilder { return &NormalBuilder{} } func (b *NormalBuilder) setWindowType() { b.windowType = "Wooden Window" } func (b *NormalBuilder) setDoorType() { b.doorType = "Wooden Door" } func (b *NormalBuilder) setNumFloor() { b.floor = 3 } func (b *NormalBuilder) setSwimPool() { b.swimPool = "None" } func (b *NormalBuilder) getHouse() House { return House{ doorType: b.doorType, windowType: b.windowType, swimPool: b.swimPool, floor: b.floor, } }
- 跟上一步同理,新建别墅具体建设者
cottagesBuilder.go
文件,代码如下:
package main type cottagesBuilder struct { windowType string doorType string swimPool string floor int } func newCottagesBuilder() *cottagesBuilder { return &cottagesBuilder{} } func (b *cottagesBuilder) setWindowType() { b.windowType = "Glass Window" } func (b *cottagesBuilder) setDoorType() { b.doorType = "Steel Security Door" } func (b *cottagesBuilder) setNumFloor() { b.floor = 1 } func (b *cottagesBuilder) setSwimPool() { b.swimPool = "Swimming Pool" } func (b *cottagesBuilder) getHouse() House { return House{ doorType: b.doorType, windowType: b.windowType, swimPool: b.swimPool, floor: b.floor, } }
- 新建主管
director.go
,主管结构体内也是抽象建造者,其次主管有着setBuilder()
和buildHouse()
的职责,最后主管负责安排负责对象的建造次序,比如先确定门、窗、楼层,再考虑是否需要加装泳池。最终代码如下:
package main type Director struct { builder IBuilder } func newDirector(b IBuilder) *Director { return &Director{ builder: b, } } func (d *Director) setBuilder(b IBuilder) { d.builder = b } func (d *Director) buildHouse() House { d.builder.setDoorType() d.builder.setWindowType() d.builder.setNumFloor() d.builder.setSwimPool() return d.builder.getHouse() }
6.新建一个 main.go
文件,测试我们的创建者模式是否正确:
package main import ( "fmt" ) func main() { normalBuilder := getBuilder("normal") cottagesBuilder := getBuilder("cottages") director := newDirector(normalBuilder) normalHouse := director.buildHouse() fmt.Printf("Normal House Door Type: %s\n", normalHouse.doorType) fmt.Printf("Normal House Window Type: %s\n", normalHouse.windowType) fmt.Printf("Normal House SwimPool: %s\n", normalHouse.swimPool) fmt.Printf("Normal House Num Floor: %d\n", normalHouse.floor) director.setBuilder(cottagesBuilder) cottagesHouse := director.buildHouse() fmt.Printf("\nCottage House Door Type: %s\n", cottagesHouse.doorType) fmt.Printf("Cottage House Window Type: %s\n", cottagesHouse.windowType) fmt.Printf("Cottage House SwimPool: %s\n", cottagesHouse.swimPool) fmt.Printf("Cottage House Num Floor: %d\n", cottagesHouse.floor) }
- 最后,我们使用命令运行整个包
go run .
这是输出结果图:
优缺点
优点:
- 你可以分步创建对象, 暂缓创建步骤或递归运行创建步骤。
- 生成不同形式的产品时, 你可以复用相同的制造代码。
- 单一职责原则。 你可以将复杂构造代码从产品的业务逻辑中分离出来。
缺点:
- 由于该模式需要新增多个类, 因此代码整体复杂程度会有所增加。