写点什么

在 Go 中构建复杂对象: 构建器模式指南

作者:俞凡
  • 2023-12-03
    上海
  • 本文字数:3027 字

    阅读完需:约 10 分钟

本文介绍了构建器模式,介绍了如何通过构建器对象构建复杂业务对象的方法。原文: 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            |                                 | ...               |                                 +-------------------+
复制代码



在 Go 中实现构建器模式

下面是 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: Toyotafmt.Printf("Model: %s\n", car.Model) // Output: Model: Corollafmt.Printf("Year: %d\n", car.Year) // Output: Year: 2021fmt.Printf("Color: %s\n", car.Color) // Output: Color: Redfmt.Printf("Engine Size: %.1f\n", car.EngineSize) // Output: Engine Size: 1.8
复制代码


在这个例子中,我们创建了一个CarBuilder对象,用它的方法来设置Car对象的可选参数。


最后调用Build方法来获取最终的Car对象。然后打印出Car对象的字段,以验证是否设置正确。



Go 中构建器模式的高级用例

构建器模式有一些高级用例,可以在某些情况下使用。


下面介绍 Go 中构建器模式的一些高级用例。

创建构建器接口

在构建器模式基本示例中,有一个用于构建对象的 builder 结构。


不过我们可以创建 builder 接口,让不同 builder 结构实现其接口。


当我们需要使用相同模式构建不同类型的对象时,这非常有用。


假设有两种类型的汽车: 电动汽车和汽油汽车,有相同的可选参数,但有不同的必需参数。


在这种情况下,可以创建一个CarBuilder接口,指定构建汽车所需的方法,然后创建两个实现CarBuilder接口的结构: ElectricCarBuilderGasolineCarBuilder


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}
复制代码


ElectricCarBuilderGaslineCarBuilder都嵌入了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)}
复制代码


在本例中,我们创建了ElectricCarBuilderGasolineCarBuilder,并分别创建了一辆电动车和一辆汽油车。


CreateCar函数接受CarBuilder接口,并在最后调用Build方法创建Car对象之前,使用构建器的方法设置必需的字段。




你好,我是俞凡,在 Motorola 做过研发,现在在 Mavenir 做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI 等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!

发布于: 刚刚阅读数: 5
用户头像

俞凡

关注

公众号:DeepNoMind 2017-10-18 加入

俞凡,Mavenir Systems研发总监,关注高可用架构、高性能服务、5G、人工智能、区块链、DevOps、Agile等。公众号:DeepNoMind

评论

发布
暂无评论
在Go中构建复杂对象: 构建器模式指南_golang_俞凡_InfoQ写作社区