轻松构建复杂对象:Go中的Builder模式介绍
联系作者@:微信公众号,Medium,LinkedIn,Twitter
在 Go 语言中,设计模式是实现软件工程最佳实践的一种方式。其中,建造者模式(Builder Pattern) 是一种创建型设计模式,用于分步骤地创建复杂对象,同时避免构造函数中参数过多的情况。
建造者模式的核心概念
- 意图:将复杂对象的构建过程与其表示分离,使得相同的构建过程可以创建不同的表示。
- 适用场景:
- 当创建复杂对象需要分步骤进行时。
- 当构造函数参数过多或参数组合导致对象的创建复杂时。
- 优点:
- 将对象的创建和表示分离,符合单一职责原则。
- 更加灵活,便于扩展。
- 缺点:
- 增加了类的复杂性。
- 对简单对象的创建可能略显多余。
建造者模式的结构
建造者模式主要包含以下几个部分:
- Product:需要创建的复杂对象。
- Builder:定义创建对象的接口,包含所有构建步骤。
- ConcreteBuilder:具体实现 Builder 接口,完成各部分构建。
- Director:指导构建过程,定义创建对象的顺序。
Go语言中的实现
以下是一个使用Go语言实现建造者模式的示例,以组装电脑为例:
1. 定义产品结构体
1 2 3 4 5 6 7 8
| type Computer struct { CPU string Memory string Mainboard string HardDisk string GPU string }
|
2. 定义建造者接口
1 2 3 4 5 6 7 8 9
| type ComputerBuilder interface { AddCPU() AddMemory() AddMainboard() AddHardDisk() AddGPU() GetComputer() Computer }
|
3. 实现具体建造者
办公型电脑建造者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| type OfficeModelBuilder struct { Computer }
func (ob *OfficeModelBuilder) AddCPU() { ob.CPU = "Intel-i3" }
func (ob *OfficeModelBuilder) AddMemory() { ob.Memory = "8G" }
func (ob *OfficeModelBuilder) AddMainboard() { ob.Mainboard = "B460" }
func (ob *OfficeModelBuilder) AddHardDisk() { ob.HardDisk = "256G HDD" }
func (ob *OfficeModelBuilder) AddGPU() { ob.GPU = "Intel HD630" }
func (ob *OfficeModelBuilder) GetComputer() Computer { return Computer{ CPU: ob.CPU, Memory: ob.Memory, Mainboard: ob.Mainboard, HardDisk: ob.HardDisk, GPU: ob.GPU, } }
|
游戏型电脑建造者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| type GameModelBuilder struct { Computer }
func (gb *GameModelBuilder) AddCPU() { gb.CPU = "Intel-i9" }
func (gb *GameModelBuilder) AddMemory() { gb.Memory = "32G" }
func (gb *GameModelBuilder) AddMainboard() { gb.Mainboard = "X460" }
func (gb *GameModelBuilder) AddHardDisk() { gb.HardDisk = "512G SSD, 1T HDD" }
func (gb *GameModelBuilder) AddGPU() { gb.GPU = "NVIDIA GTX3090" }
func (gb *GameModelBuilder) GetComputer() Computer { return Computer{ CPU: gb.CPU, Memory: gb.Memory, Mainboard: gb.Mainboard, HardDisk: gb.HardDisk, GPU: gb.GPU, } }
|
4. 指挥者实现
1 2 3 4 5 6 7 8 9 10 11 12 13
| type Director struct { builder ComputerBuilder }
func (d *Director) Build() Computer { d.builder.AddCPU() d.builder.AddMemory() d.builder.AddMainboard() d.builder.AddHardDisk() d.builder.AddGPU() return d.builder.GetComputer() }
|
5. 测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| func main() { officeBuilder := &OfficeModelBuilder{} director := Director{officeBuilder} computer1 := director.Build() fmt.Printf("办公型主机配置:%v \n", computer1)
gameBuilder := &GameModelBuilder{} director.builder = gameBuilder computer2 := director.Build() fmt.Printf("游戏型主机配置:%v \n", computer2) }
办公型主机配置:{Intel-i3 8G B460 256G HDD Intel HD630} 游戏型主机配置:{Intel-i9 32G X460 512G SSD, 1T HDD NVIDIA GTX3090}
|
6. Golang 实现的相关思考
以上实现参考了Java 的实现方法,但是 Golang 应该有自己的特色。Go Is Not Java
去掉 Director
:
在 Go 的实现中,Director
并不是必需的。将构建逻辑直接放在建造器函数里(OfficeComputerBuilder
和 GameComputerBuilder
)更符合 Go 的简单直接风格。
函数链式调用:
GenericBuilder
使用链式方法(方法返回自身),方便一步步构建对象。
更加清晰的职责划分:
GenericBuilder
是一个通用建造器,而具体的 OfficeComputerBuilder
和 GameComputerBuilder
负责生成具体的电脑配置。
避免过度设计:
Go 提倡简洁,不必强求像 Java 那样使用复杂的设计模式实现。
你也可以参考文章: Design patterns in Golang — The Builder | by Surya Reddy | Medium
总结
- 建造者模式通常适用于有多个构造器参数或者需要较多构建步骤的场景。使用建造者模式可以精简构造器参数的数量,让构建过程更有条理。
- 可以为同一个产品提供多个不同的实现。比如,在上面的代码中,为
Computer
类型创建了两个不同的实现:通过NewOfficeModelBuilder
构建的 office computer,以及通过NewGameModelBuilder
构建的 game computer
- 可以应用于构建过程不允许被中断的场景。仍然参考刚才的代码,
Computer
类型的对象要么彻底完成,要么压根没有创建,不会存在中间状态,这是因为struct director
封装了相应的过程,中间状态仅存在于ConcreteBuilder中。
更多该系列文章,参考medium链接:
https://wesley-wei.medium.com/list/you-should-know-in-golang-e9491363cd9a
English post: https://programmerscareer.com/golang-builder-pattern/
作者:微信公众号,Medium,LinkedIn,Twitter
发表日期:原文在 2024-11-17 17:53 时创作于 https://programmerscareer.com/zh-cn/golang-builder-pattern/
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
评论