在Go中構(gòu)建復雜對象: 構(gòu)建器模式指南
構(gòu)建具有許多可選參數(shù)的復雜對象可能是一項艱巨的任務(wù)。
當處理具有許多可選參數(shù)的對象時,傳統(tǒng)構(gòu)造函數(shù)和setter方法會變得很麻煩。
本文將探討構(gòu)建器模式(builder pattern),這是一種允許創(chuàng)建具有許多可選參數(shù)的復雜對象的設(shè)計模式。
我們將介紹基于Go的構(gòu)建器模式示例實現(xiàn),并討論如何創(chuàng)建同一對象的不同變體。
+----------------+ +-------------------+
| Director | directs | Builder |
+----------------+ +-------------------+
| construct() | ------------> | buildPart1() |
| setBuilder() | | buildPart2() |
+----------------+ | getProduct() |
+-------------------+
|
V
+-------------------+
| Product |
+-------------------+
| field1 |
| field2 |
| ... |
+-------------------+
在Go中實現(xiàn)構(gòu)建器模式
下面是golang中構(gòu)建器模式示例:
type Car struct {
Make string
Model string
Year int
Color string
EngineSize float64
}
type CarBuilder struct {
Car
}
func (cb *CarBuilder) SetMake(make string) *CarBuilder {
cb.Make = make
return cb
}
func (cb *CarBuilder) SetModel(model string) *CarBuilder {
cb.Model = model
return cb
}
func (cb *CarBuilder) SetYear(year int) *CarBuilder {
cb.Year = year
return cb
}
func (cb *CarBuilder) SetColor(color string) *CarBuilder {
cb.Color = color
return cb
}
func (cb *CarBuilder) SetEngineSize(engineSize float64) *CarBuilder {
cb.EngineSize = engineSize
return cb
}
func (cb *CarBuilder) Build() *Car {
return &cb.Car
}
CarBuilder結(jié)構(gòu)嵌入了一個Car對象,所以它的所有字段都可以被構(gòu)建器訪問。
CarBuilder結(jié)構(gòu)具有設(shè)置Car對象可選參數(shù)的方法,每個方法返回指向CarBuilder結(jié)構(gòu)體的指針,以允許鏈式調(diào)用。
CarBuilder結(jié)構(gòu)體上的Build方法返回指向被構(gòu)建的Car對象的指針。
下面是使用CarBuilder的例子:
carBuilder := &CarBuilder{}
car := carBuilder.
SetMake("Toyota").
SetModel("Corolla").
SetYear(2021).
SetColor("Red").
SetEngineSize(1.8).
Build()
fmt.Printf("Make: %s\n", car.Make) // Output: Make: Toyota
fmt.Printf("Model: %s\n", car.Model) // Output: Model: Corolla
fmt.Printf("Year: %d\n", car.Year) // Output: Year: 2021
fmt.Printf("Color: %s\n", car.Color) // Output: Color: Red
fmt.Printf("Engine Size: %.1f\n", car.EngineSize) // Output: Engine Size: 1.8
在這個例子中,我們創(chuàng)建了一個CarBuilder對象,用它的方法來設(shè)置Car對象的可選參數(shù)。
最后調(diào)用Build方法來獲取最終的Car對象。然后打印出Car對象的字段,以驗證是否設(shè)置正確。
Go中構(gòu)建器模式的高級用例
構(gòu)建器模式有一些高級用例,可以在某些情況下使用。
下面介紹Go中構(gòu)建器模式的一些高級用例。
創(chuàng)建構(gòu)建器接口
在構(gòu)建器模式基本示例中,有一個用于構(gòu)建對象的builder結(jié)構(gòu)。
不過我們可以創(chuàng)建builder接口,讓不同builder結(jié)構(gòu)實現(xiàn)其接口。
當我們需要使用相同模式構(gòu)建不同類型的對象時,這非常有用。
假設(shè)有兩種類型的汽車: 電動汽車和汽油汽車,有相同的可選參數(shù),但有不同的必需參數(shù)。
在這種情況下,可以創(chuàng)建一個CarBuilder接口,指定構(gòu)建汽車所需的方法,然后創(chuàng)建兩個實現(xiàn)CarBuilder接口的結(jié)構(gòu): ElectricCarBuilder和GasolineCarBuilder。
type CarBuilder interface {
SetMake(make string) CarBuilder
SetModel(model string) CarBuilder
SetYear(year int) CarBuilder
SetColor(color string) CarBuilder
SetEngineSize(engineSize float64) CarBuilder
Build() Car
}
type ElectricCarBuilder struct {
Car
}
type GasolineCarBuilder struct {
Car
}
ElectricCarBuilder和GaslineCarBuilder都嵌入了Car結(jié)構(gòu)體并實現(xiàn)了CarBuilder接口。
然后可以自己實現(xiàn)制造汽車所需的方法。
func (b *ElectricCarBuilder) SetMake(make string) CarBuilder {
b.Make = make
return b
}
func (b *ElectricCarBuilder) SetModel(model string) CarBuilder {
b.Model = model
return b
}
func (b *ElectricCarBuilder) SetYear(year int) CarBuilder {
b.Year = year
return b
}
func (b *ElectricCarBuilder) SetColor(color string) CarBuilder {
b.Color = color
return b
}
func (b *ElectricCarBuilder) SetEngineSize(engineSize float64) CarBuilder {
b.EngineSize = engineSize
return b
}
func (b *ElectricCarBuilder) Build() Car {
return b.Car
}
func (b *GasolineCarBuilder) SetMake(make string) CarBuilder {
b.Make = make
return b
}
func (b *GasolineCarBuilder) SetModel(model string) CarBuilder {
b.Model = model
return b
}
func (b *GasolineCarBuilder) SetYear(year int) CarBuilder {
b.Year = year
return b
}
func (b *GasolineCarBuilder) SetColor(color string) CarBuilder {
b.Color = color
return b
}
func (b *GasolineCarBuilder) SetEngineSize(engineSize float64) CarBuilder {
b.EngineSize = engineSize
return b
}
func (b *GasolineCarBuilder) Build() Car {
return b.Car
}
我們因此可以基于接口創(chuàng)建汽車,也可以使用相同的接口做模擬。
func CreateCar(builder CarBuilder) Car {
return builder.
SetMake("Toyota").
SetModel("Corolla").
SetYear(2022).
SetColor("blue").
SetEngineSize(2.0).
Build()
}
func main() {
electricCarBuilder := &ElectricCarBuilder{}
gasolineCarBuilder := &GasolineCarBuilder{}
electricCar := CreateCar(electricCarBuilder)
gasolineCar := CreateCar(gasolineCarBuilder)
fmt.Printf("Electric car: %+v\n", electricCar)
fmt.Printf("Gasoline car: %+v\n", gasolineCar)
}
在本例中,我們創(chuàng)建了ElectricCarBuilder和GasolineCarBuilder,并分別創(chuàng)建了一輛電動車和一輛汽油車。
CreateCar函數(shù)接受CarBuilder接口,并在最后調(diào)用Build方法創(chuàng)建Car對象之前,使用構(gòu)建器的方法設(shè)置必需的字段。
參考資料:
[1]Building Complex Objects in Go: A Guide to the Builder Pattern: https://dsysd-dev.medium.com/building-complex-objects-in-go-a-guide-to-the-builder-pattern-1a64bc0eb3ee