概念
建造者模式(Builder Pattern)讲将一个复杂的对象的构建与它的表示分离, 使得同样的构建过程可以创建不同的表示。 使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式
具体实现是:比如:构建一个产品
- 产品, 2个内部部件, 产品有添加部件的方法。
- 有一个抽象的构建接口, 接口分为2个接口, 可以被具体的构建者实现。
- 有一个构建指挥者, 它来做具体的构建, 它继承了构建接口, 接收具体的创建者, 通过自己的构建接口, 调用具体创建者的创建方法。
- 有两个具体的创建接口实现者, 它包含产品结构体, 构建接口要调用产品接口, 给具体的产品装配。
- 具体创建者接口实现者,传递给创建指挥者, 构建了产品以后, 具体实现者可以调用自身获取产品, 展示产品。
UML图
<img src="doc/builder_pattern.jpeg"/>
模式的场景和优缺点
使用场景
1、用于创建一些复杂的对象, 这些对象内部构建的顺序是稳定的, 对象内部构建通常面临着复杂的变化。
2、需要生成的对象内部属性本身相互依赖
优点
1、建造者独立,易扩展
2、便于控制细节风险
缺点
1、产品必须有共同点,范围有限制
2、如内部变化复杂,会有很多的建造类
代码实现
package main
import "fmt"
//Builder 是生成器接口
type Builder interface {
BuildPart1()
BuildPart2()
}
// Director ...
type Director struct {
builder Builder
}
// NewDirector ... 构建指挥者
func NewDirector(builder Builder) *Director {
return &Director{
builder: builder,
}
}
// Construct Product 指挥者,指挥不同的Build组装Product
func (d *Director) Construct() {
d.builder.BuildPart1()
d.builder.BuildPart2()
}
type Product struct {
part1 string
part2 string
}
func (p *Product) AddPart1(part string) {
p.part1 = part
}
func (p *Product) AddPart2(part string) {
p.part2 = part
}
func (p *Product) ShowProduct() {
fmt.Println("Product part1:", p.part1, "part2:", p.part2)
}
// ConcreteBuilder1 ...
type ConcreteBuilder1 struct {
Product
}
// BuildPart1 ...
func (b *ConcreteBuilder1) BuildPart1() {
b.Product.AddPart1("部件1")
}
// BuildPart2 ...
func (b *ConcreteBuilder1) BuildPart2() {
b.Product.AddPart2("部件2")
}
// GetResult ...
func (b *ConcreteBuilder1) GetProduct() Product {
return b.Product
}
// ContreteBuilder2 ...
type ContreteBuilder2 struct {
Product
}
// BuildPart1 ...
func (b *ContreteBuilder2) BuildPart1() {
b.Product.AddPart1("部件a")
}
// BuildPart2 ...
func (b *ContreteBuilder2) BuildPart2() {
b.Product.AddPart2("部件b")
}
// GetResult ...
func (b *ContreteBuilder2) GetProduct() Product {
return b.Product
}
func main() {
b1 := &ConcreteBuilder1{}
b2 := &ContreteBuilder2{}
d1 := NewDirector(b1)
d2 := NewDirector(b2)
d1.Construct()
d2.Construct()
fmt.Println(b1.GetProduct())
fmt.Println(b2.GetProduct())
}