脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|shell|

服务器之家 - 脚本之家 - Golang - 在Go中构建复杂对象: 构建器模式指南

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

2024-01-15 14:29DeepNoMind Golang

本文我们介绍了构建器模式,介绍了如何通过构建器对象构建复杂业务对象的方法。

构建具有许多可选参数的复杂对象可能是一项艰巨的任务。

当处理具有许多可选参数的对象时,传统构造函数和setter方法会变得很麻烦。

本文将探讨构建器模式(builder pattern),这是一种允许创建具有许多可选参数的复杂对象的设计模式。

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

我们将介绍基于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: 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中构建器模式的高级用例

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

下面介绍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对象之前,使用构建器的方法设置必需的字段。

参考资料:

[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

原文地址:https://mp.weixin.qq.com/s?__biz=MzU2MTgxODgwNA==&mid=2247487703&idx=1&sn=cd70f7bd976685441441a47c83204692

延伸 · 阅读

精彩推荐
  • Golangprometheus client_go为应用程序自定义监控指标

    prometheus client_go为应用程序自定义监控指标

    这篇文章主要为大家介绍了prometheus client_go为应用程序自定义监控指标详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升...

    a朋6952023-02-16
  • GolangGo语言如何操纵Kafka保证无消息丢失

    Go语言如何操纵Kafka保证无消息丢失

    Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。该项目的目标是为处理实时数据提供一个统一、高吞吐、低延迟的平台。其持久化...

    Golang梦工厂4612021-09-14
  • Golang利用rpm打包上线部署golang代码的方法教程

    利用rpm打包上线部署golang代码的方法教程

    RPM是RPM Package Manager(RPM软件包管理器)的缩写,这篇文章主要给大家介绍了关于利用rpm打包上线部署golang代码的相关资料,文中通过示例代码介绍的非常详...

    xiaorui2082020-05-13
  • GolangGo语言字符串基础示例详解

    Go语言字符串基础示例详解

    这篇文章主要为大家介绍了Go语言字符串基础的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...

    枫少文6772021-12-06
  • GolangGo reflect 反射原理示例详解

    Go reflect 反射原理示例详解

    这篇文章主要为大家介绍了Go reflect 反射原理示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...

    飞天薯条5372022-12-02
  • GolangGo 处理大数组使用 for range 和 for 循环的区别

    Go 处理大数组使用 for range 和 for 循环的区别

    这篇文章主要介绍了Go处理大数组使用for range和for循环的区别,对于遍历大数组而言,for循环能比for range循环更高效与稳定,这一点在数组元素为结构体类...

    机器铃砍菜刀8332022-10-07
  • GolangGo 中常用的四大重构技术

    Go 中常用的四大重构技术

    这是我常应用于代码的技术。它包括提取一段按意图分组的代码,并转移到新方法中。通过提取可以将一个长方法或函数拆分为一些小方法,这些小方法将...

    幽鬼5092021-11-03
  • Golang解析Golang中引用类型是否进行引用传递

    解析Golang中引用类型是否进行引用传递

    这篇文章主要为大家介绍了Golang中引用类型是否进行引用传递剖析详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加...

    刘悦的技术博客8352022-08-29