建造者模式
最近一直在寫框架,這個系列也好久沒更新了,抽時間更新一篇~
概述
wiki: 建造者模式(Builder Pattern):將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。
直白一點的說,就是將我們在開發過程中遇到的大型物件,拆分成多個小物件,然後將多個小物件組裝成大物件,並且對外部隱藏建造過程.
結構
建造者模式由一下4個部分組成
-
Builder
: 抽象建造者 -
ConcreteBuilder
: 具體建造者 -
Director
: 指揮者 -
Production
: 產品(大型產品以及拆分成的小型產品)
類圖 && 時序圖
(圖源網路)
從上面兩張圖可以看出建造者模式的使用流程:
- 建立大型產品建造者
- 建立指揮者
- 將建造者傳入指揮者物件中
- 由指揮者指揮建造者建立物件,並返回
舉個栗子
說一個網上說爛了的組裝汽車的栗子吧,
比如說我是個老司機,但是除了開車還想造車,但是車的構造實在是太複雜了,那麼我們就可以將車拆分...
4個輪子、1個底盤、1個駕駛位...
好了,為了簡便,就造這三個吧,先造個爬犁出來...
所以我需要一個大型專案構造者CarBuilder
:
type CarBuilder struct {
Car *Car
}
func (cb *CarBuilder) GetResult() interface{} {
return cb.Car
}
func (cb *CarBuilder) NewProduct() {
cb.Car = new(Car)
}
func (cb *CarBuilder) BuildWheels() {
cb.Car.Wheels = "build wheels"
}
func (cb *CarBuilder) BuildChassis() {
cb.Car.Chassis = "build chassis"
}
func (cb *CarBuilder) BuildSeat() {
cb.Car.Seat = "build seat"
}
複製程式碼
這個建造者實現了Builder
介面:
type Builder interface {
NewProduct() // 建立一個空產品
BuildWheels() // 建造輪子
BuildChassis() // 建造底盤
BuildSeat() // 建造駕駛位
GetResult() interface{} // 獲取建造好的產品
}
複製程式碼
下面要把具體建造者傳入指揮者:
type Director struct {
builder Builder
}
func (d *Director) SetBuilder(builder Builder) {
d.builder = builder
}
複製程式碼
現在指揮者和建造者都已經準備好了,可以進行建造了,呼叫指揮者的Generate()
方法:
func (d *Director) Generate() *Car {
d.builder.NewProduct()
d.builder.BuildChassis()
d.builder.BuildSeat()
d.builder.BuildWheels()
return d.builder.GetResult().(*Car)
}
複製程式碼
這樣,就得到了我們需要的 Car
物件:
func main() {
// 建立一個指揮者
director := new(Director)
// 建立建造者
builder := new(CarBuilder)
director.SetBuilder(builder)
car := director.Generate()
car.Show()
}
複製程式碼
總結
上面的程式碼,是將一個本來就不是很複雜的物件,強行拆分,只是將其中的欄位設為最簡單的string
型別,實際上,這些欄位應該是更小的物件結構體,然後還可以繼續把這些小結構體繼續拆分,拆分為最小單元,這樣才是結構最清晰的思路.
本來想舉一個應用在實際專案中的栗子的,但是框架還沒有寫完,這樣,先佔個坑,等bingo
框架完成後我會再來補充這一部分.
上述程式碼均放在 golang-design-patterns 這個倉庫中
打個廣告,推薦一下自己寫的 go web框架 bingo,求star,求PR ~