Golang設計模式學習筆記--建造者模式
阿新 • • 發佈:2021-08-16
建造者模式
在軟體開發中有時需要建立一個複雜的物件,這個物件有很多小物件按照一定的步驟組成,例如計算機是由主機板、記憶體、cpu、硬碟、顯示卡等元件組成,採購員不可能自己組裝計算機,而是將計算機的配置要求告訴計算機銷售公司,計算機銷售公司再安排技術人員組裝計算機,再交給採購員
生活中這種例子也有很多,比如遊戲中不同角色的性格、能力、臉型,體型、髮型、服裝等各有差異,汽車的方向盤,輪胎、發動機、輪胎、也有多鍾多樣。每封郵件的主題,內容附件等內容也各不相同。
建造者模式的定義
是指將一個複雜的物件的構造與表象分離,使得同樣的構造過程可以建立不同的表示,他將變與不變分離,即使產品的組成部分是不變的,但是每一部分是可以靈活選擇的。
建造者模式的優點
- 封裝性好,構建和表示分離
- 擴充套件性好,各個不同的建造者相互獨立,有利於系統的解耦
- 呼叫者不必知道產品的內部組成細節,建造者可以對建立過程逐步細化,也不會影響到其他模組
建造者模式的缺點
- 產品的組成部分必須相同,限制了其使用範圍
- 如果產品的內部變化過大,則建造者也要同步進行修改,後期維護成本比較大
建造者模式和工廠模式關注點不同,建造者模式更關注零部件的組裝過程,而工廠模式更關注的是建立過程。但是兩者可以結合使用
這裡可以理解為:每個零件需要工廠來生產,但是實際負責組裝的工廠,這裡叫做建造者。
建造者模式的要素
建造者模式由產品(Product)、指揮者(Director)、抽象建立者(Builder)、具體建立者(Concrete Builder)4個要素組成
具體程式碼分析
- 產品
包含getter setter方法
// Product 是產品 type Product struct { partA string partB string partC string } func (p *Product) PartA() string { return p.partA } func (p *Product) SetPartA(partA string) { p.partA = partA } func (p *Product) PartB() string { return p.partB } func (p *Product) SetPartB(partB string) { p.partB = partB } func (p *Product) PartC() string { return p.partC } func (p *Product) SetPartC(partC string) { p.partC = partC }
- 指揮者
包含一個建造函式Construct()返回產品
// Director 是指揮者
type Director struct {
builder Builder
}
func (d *Director)Construct() interface{} {
d.builder.newProduct()
d.builder.buildPartA()
d.builder.buildPartB()
d.builder.buildPartC()
return d.builder.getResult()
}
func NewDirector(builder Builder) *Director {
return &Director{
builder: builder,
}
}
- 抽象建造者
// Builder 是一個抽象建造者
type Builder interface {
// 建立新產品
newProduct()
buildPartA()
buildPartB()
buildPartC()
// 返回產品物件
getResult() interface{}
}
- 具體建造者
實現Builder介面
// ConcreteBuilder 是具體的建造者
type ConcreteBuilder struct {
product *Product
}
func (cb *ConcreteBuilder)newProduct() {
cb.product = &Product{}
}
func (cb *ConcreteBuilder)buildPartA() {
cb.product.SetPartA("A部分已構建")
}
func (cb *ConcreteBuilder) buildPartB() {
cb.product.SetPartB("B部分已構建")
}
func (cb *ConcreteBuilder)buildPartC() {
cb.product.SetPartC("C部分已構建")
}
// 返回產品物件
func (cb *ConcreteBuilder)getResult() interface{} {
return cb.product
}
- 實際呼叫
b:= &builder.ConcreteBuilder{}
director := builder.NewDirector(b)
product := director.Construct()
適用場景
- 相同的方法,不同的執行順序,產生不同的結果。
- 多個部件或零件,都可以裝配到一個物件中,但是產生的結果又不相同。
- 產品類非常複雜,或者產品類中不同的呼叫順序產生不同的作用。
- 初始化一個物件特別複雜,引數多,而且很多引數都具有預設值。