附录2.生成器模式
生成器模式是一种创建型设计模式,使你能够分步骤创建复杂对象.
与其他创建型模式不同,生成器模式不要求产品拥有通用接口.这使得用相同的创建过程生成不同的产品成为可能.
PART1. 概念示例
当所需产品较为复杂且需要多个步骤才能完成时,可以使用生成器模式.在这种情况下,使用多个构造方法比仅仅使用一个复杂可怕的构造函数更简单.但分多个步骤进行构建的策略也有其问题.分为多个步骤进行构建的潜在问题在于:构建不完整的和不稳定的产品可能会被暴露给客户端.生成器模式能够在产品完成构建之前使其处于私密状态.
1.1 背景故事
现有2种房屋:
冰屋
普通房屋
这两种房屋的建造步骤都是相同的(例如先装窗户、再装门,最后装地板).该如何组织这个建造过程?
1.2 房屋结构体
房屋结构体实际上就是我们完成所有建造步骤后,最终对外提供的产品
pattern/house.go:
package pattern
// House 房屋结构体 即最终对外提供的产品
type House struct {
windowType string // windowType 窗户类型
doorType string // doorType 门的类型
floor int // floor 房屋楼层数
}
// GetWindowType 本方法用于获取房屋的窗户类型
func (h House) GetWindowType() string {
return h.windowType
}
// GetDoorType 本方法用于获取房屋的门的类型
func (h House) GetDoorType() string {
return h.doorType
}
// GetFloor 本方法用于获取房屋的楼层数
func (h House) GetFloor() int {
return h.floor
}1.3 生成器接口
接口定义行为.本例中的生成器接口定义了创建一个房屋所必须经历的过程,也就是创建一个房屋的行为
pattern/iBuilder.go
1.4 普通房屋生成器
pattern/normalBuilder.go:
1.5 冰屋生成器
pattern/iglooBuilder.go:
1.6 管理者结构体
以上两个具体的生成器类仅仅定义了建造一个房屋(无论是普通房屋还是冰屋)的每个具体过程,但还缺少一个角色,该角色用于编排这些过程的执行顺序.在本例中,可以理解为:无论是建造一个冰屋还是普通房屋,其建造顺序应该是固定的:
step1. 造窗户
step2. 造门
step3. 确定楼层数
而管理者结构体的职责就是确定这些过程的执行顺序,并在这些过程都按顺序执行完毕后,返回被创建出的产品
pattern/director.go:
1.7 提供对外暴露的创建具体生成器的方法
pattern/IBuilder.go:
1.8 客户端创建房屋
main.go:
执行结果:
PART2. 示例相关UML

PART3. 生成器模式工作流程

PART4. 生成器模式使用场景
当开发者希望创建不同形式的产品时,可以使用生成器模式
如果开发者需要创建各种形式的产品,且这些产品的制造过程相似,且产品之间的差别不大(例如本例中的冰屋和普通房屋),可以使用生成器模式
如果需要使用构造函数,且构造函数中的参数很多时,可以使用生成器模式
当需要构建同一个对象的不同表示时,可以使用生成器模式.换言之,当需要创建具有不同特征的同一类对象时,可使用生成器模式
PART5. 生成器模式的优缺点
5.1 优点
在生成器模式中,产品内部组成的细节对客户端不可见,将产品的创建过程和产品自身解耦,使相同的创建过程可以创建不同的产品对象
在生成器模式中,每个具体生成器都相对独立,因此可以十分方便地替换具体生成器或增加新的具体生成器,且无须修改原有类库的代码(无侵入式的修改才是高明的修改),系统扩展方便,符合开闭原则(Open/Closed Principle,OCP),设计灵活性和代码可读性较高
生成器模式可以将复杂产品的创建步骤分解在不同的方法中,使创建过程更清晰,更易于使用程序控制创建过程
5.2 缺点
使用生成器模式创建的产品组成部分都类似,如果不同产品之间的差异很大(如很多组成部分都不相同),则不适合使用生成器模式,因此其使用范围有限
在生成器模式中,需要为不同类型的产品创建单独的具体生成器,因此代码量较大.如果系统比较大,则会增加系统的理解难度和运行成本
Last updated