Michal Matlon @Unsplash本文介绍了构建器模式,介绍了如何通过构建器对象构建复杂业务对象的方法。原文: Building Complex Objects in Go: A Guide to the Builder Pattern
构建具有许多可选参数的复杂对象可能是一项艰巨的任务。
当处理具有许多可选参数的对象时,传统构造函数和setter方法会变得很麻烦。
本文将探讨构建器模式(builder pattern),这是一种允许创建具有许多可选参数的复杂对象的设计模式。
我们将介绍基于Go的构建器模式示例实现,并讨论如何创建同一对象的不同变体。
+----------------+ +-------------------+
| Director | directs | Builder |
+----------------+ +-------------------+
| construct() | ------------> | buildPart1() |
| setBuilder() | | buildPart2() |
+----------------+ | getProduct() |
+-------------------+
|
V
+-------------------+
| Product |
+-------------------+
| field1 |
| field2 |
| ... |
+-------------------+
下面是golang中构建器模式示例。
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
结构嵌入了一个Car
对象,所以它的所有字段都可以被构建器访问。
CarBuilder
结构具有设置Car
对象可选参数的方法,每个方法返回指向CarBuilder
结构体的指针,以允许链式调用。
CarBuilder
结构体上的Build
方法返回指向被构建的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
在这个例子中,我们创建了一个CarBuilder
对象,用它的方法来设置Car
对象的可选参数。
最后调用Build
方法来获取最终的Car
对象。然后打印出Car
对象的字段,以验证是否设置正确。
构建器模式有一些高级用例,可以在某些情况下使用。
下面介绍Go中构建器模式的一些高级用例。
在构建器模式基本示例中,有一个用于构建对象的builder结构。
不过我们可以创建builder接口,让不同builder结构实现其接口。
当我们需要使用相同模式构建不同类型的对象时,这非常有用。
假设有两种类型的汽车: 电动汽车和汽油汽车,有相同的可选参数,但有不同的必需参数。
在这种情况下,可以创建一个CarBuilder
接口,指定构建汽车所需的方法,然后创建两个实现CarBuilder
接口的结构: 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
结构体并实现了CarBuilder
接口。
然后可以自己实现制造汽车所需的方法。
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
}
我们因此可以基于接口创建汽车,也可以使用相同的接口做模拟。
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)
}
在本例中,我们创建了ElectricCarBuilder
和GasolineCarBuilder
,并分别创建了一辆电动车和一辆汽油车。
CreateCar
函数接受CarBuilder
接口,并在最后调用Build
方法创建Car
对象之前,使用构建器的方法设置必需的字段。
你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!
本文由 mdnice 多平台发布