1. 程式人生 > 其它 >Golang設計模式學習筆記--建造者模式

Golang設計模式學習筆記--建造者模式

建造者模式

在軟體開發中有時需要建立一個複雜的物件,這個物件有很多小物件按照一定的步驟組成,例如計算機是由主機板、記憶體、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()

適用場景

  • 相同的方法,不同的執行順序,產生不同的結果。
  • 多個部件或零件,都可以裝配到一個物件中,但是產生的結果又不相同。
  • 產品類非常複雜,或者產品類中不同的呼叫順序產生不同的作用。
  • 初始化一個物件特別複雜,引數多,而且很多引數都具有預設值。

完整程式碼傳送門