创建型设计模式-生成器模式 什么是生成器模式 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象
生成器(Builder)接口声明在所有类型生成器中通用的产品 构造步骤
具体生成器(Concrete Builders)提供构造过程的不同实现。 具体生成器也可以构造不遵循通用接口的产品。
产品(Products)是最终生成的对象。由不同生成器构造的 产品无需属于同一类层次结构或接口。
主管(Director)类定义调用构造步骤的顺序,这样你就可以 创建和复用特定的产品配置。
客户端(Client)必须将某个生成器对象与主管类关联。一 般情况下,你只需通过主管类构造函数的参数进行一次性关 联即可。此后主管类就能使用生成器对象完成后续所有的构 造任务。但在客户端将生成器对象传递给主管类制造方法时 还有另一种方式。在这种情况下,你在使用主管类生产产品 时每次都可以使用不同的生成器
Example 生成器接口 package maintype IBuilder interface { setWindowType() setDoorType() setNumFloor() getHouse() House } func getBuilder (builderType string ) IBuilder { if builderType == "normal" { return newNormalBuilder() } if builderType == "igloo" { return newIglooBuilder() } return nil }
具体生成器A package maintype NormalBuilder struct { windowType string doorType 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 = 2 } func (b *NormalBuilder) getHouse() House { return House{ doorType: b.doorType, windowType: b.windowType, floor: b.floor, } }
具体生成器B package maintype IglooBuilder struct { windowType string doorType string floor int } func newIglooBuilder () *IglooBuilder { return &IglooBuilder{} } func (b *IglooBuilder) setWindowType() { b.windowType = "Snow Window" } func (b *IglooBuilder) setDoorType() { b.doorType = "Snow Door" } func (b *IglooBuilder) setNumFloor() { b.floor = 1 } func (b *IglooBuilder) getHouse() House { return House{ doorType: b.doorType, windowType: b.windowType, floor: b.floor, } }
产品 package maintype House struct { windowType string doorType string floor int }
主管 package maintype 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() return d.builder.getHouse() }
客户端 package mainimport "fmt" func main () { normalBuilder := getBuilder("normal" ) iglooBuilder := getBuilder("igloo" ) 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 Num Floor: %d\n" , normalHouse.floor) director.setBuilder(iglooBuilder) iglooHouse := director.buildHouse() fmt.Printf("\nIgloo House Door Type: %s\n" , iglooHouse.doorType) fmt.Printf("Igloo House Window Type: %s\n" , iglooHouse.windowType) fmt.Printf("Igloo House Num Floor: %d\n" , iglooHouse.floor) }
适用场景
使 用 生 成 器 模 式 可 避 免 “重 叠 构 造 函 数 (telescopic constructor)”的出现
使 用 生 成 器 模 式 可 避 免 “重 叠 构 造 函 数 (telescopic constructor)”的出现
当你希望使用代码创建不同形式的产品(例如石头或木头房 屋)时,可使用生成器模式。
如果你需要创建的各种形式的产品,它们的制造过程相似且 仅有细节上的差异,此时可使用生成器模式。
使用生成器构造组合树或其他复杂对象
生成器模式让你能分步骤构造产品。你可以延迟执行某些步 骤而不会影响最终产品。你甚至可以递归调用这些步骤,这 在创建对象树时非常方便。
优缺点 优点
缺点
由于该模式需要新增多个类,因此代码整体复杂程度会有所 增加
与其他模式的关系
在许多设计工作的初期都会使用工厂方法(较为简单,而且 可以更方便地通过子类进行定制),随后演化为使用抽象工 厂、原型或生成器(更灵活但更加复杂)。
生成器重点关注如何分步生成复杂对象。抽象工厂专门用于 生产一系列相关对象。抽象工厂会马上返回产品,生成器则 允许你在获取产品前执行一些额外构造步骤
你可以在创建复杂组合树时使用生成器,因为这可使其构造 步骤以递归的方式运行
你可以结合使用生成器和桥接模式: 主管类负责抽象工作, 各种不同的生成器负责实现工作
抽象工厂、生成器和原型都可以用单例来实现