概念
建造者模式(Builder Pattern)講將一個(gè)復(fù)雜的對(duì)象的構(gòu)建與它的表示分離, 使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示奶赔。 使用多個(gè)簡(jiǎn)單的對(duì)象一步一步構(gòu)建成一個(gè)復(fù)雜的對(duì)象弦叶。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式符喝,它提供了一種創(chuàng)建對(duì)象的最佳方式
具體實(shí)現(xiàn)是:比如:構(gòu)建一個(gè)產(chǎn)品
- 產(chǎn)品招狸, 2個(gè)內(nèi)部部件兄世, 產(chǎn)品有添加部件的方法啼辣。
- 有一個(gè)抽象的構(gòu)建接口, 接口分為2個(gè)接口碘饼, 可以被具體的構(gòu)建者實(shí)現(xiàn)。
- 有一個(gè)構(gòu)建指揮者悲伶, 它來做具體的構(gòu)建艾恼, 它繼承了構(gòu)建接口, 接收具體的創(chuàng)建者麸锉, 通過自己的構(gòu)建接口钠绍, 調(diào)用具體創(chuàng)建者的創(chuàng)建方法。
- 有兩個(gè)具體的創(chuàng)建接口實(shí)現(xiàn)者花沉, 它包含產(chǎn)品結(jié)構(gòu)體柳爽, 構(gòu)建接口要調(diào)用產(chǎn)品接口, 給具體的產(chǎn)品裝配碱屁。
- 具體創(chuàng)建者接口實(shí)現(xiàn)者磷脯,傳遞給創(chuàng)建指揮者, 構(gòu)建了產(chǎn)品以后娩脾, 具體實(shí)現(xiàn)者可以調(diào)用自身獲取產(chǎn)品赵誓, 展示產(chǎn)品。
UML圖
<img src="doc/builder_pattern.jpeg"/>
builder_pattern.png
模式的場(chǎng)景和優(yōu)缺點(diǎn)
使用場(chǎng)景
1柿赊、用于創(chuàng)建一些復(fù)雜的對(duì)象俩功, 這些對(duì)象內(nèi)部構(gòu)建的順序是穩(wěn)定的, 對(duì)象內(nèi)部構(gòu)建通常面臨著復(fù)雜的變化碰声。
2诡蜓、需要生成的對(duì)象內(nèi)部屬性本身相互依賴
優(yōu)點(diǎn)
1、建造者獨(dú)立胰挑,易擴(kuò)展
2蔓罚、便于控制細(xì)節(jié)風(fēng)險(xiǎn)
缺點(diǎn)
1、產(chǎn)品必須有共同點(diǎn)瞻颂,范圍有限制
2脚粟、如內(nèi)部變化復(fù)雜,會(huì)有很多的建造類
代碼實(shí)現(xiàn)
package main
import "fmt"
//Builder 是生成器接口
type Builder interface {
BuildPart1()
BuildPart2()
}
// Director ...
type Director struct {
builder Builder
}
// NewDirector ... 構(gòu)建指揮者
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())
}