Builder建造者模式也是一种创建型设计模式,建造者模式就是把一个复杂的对象分成多个简单的对象,然后对这些简单的对象一步步进行构建,从而组成了一个复杂的对象。
建造者模式种有三个角色:
- 建造者(Builder)负责定义生成实例的接口
- 具体建造者(ConcreteBuilder)实现了Builder接口,定义生成实例时被调用的方法
- 指挥者(Director)负责使用Builder接口生成实例。它不依赖ConcreteBuilder
场景
本文内容我们就拿组装电脑为例,因为电脑就是由多个组件组成,且最少1个CPU,一条内存,一块主板再加一块硬盘就可以组成一台电脑主机了。又或者是加上一块高性能显卡组成游戏主机。所以我觉得组装电脑主机举例再合适不过了。
基础类型与接口
电脑建造者接口ComputerBuilder,定义了添加(组装)各个组件的方法和一个返回主机实例的方法
// Builder 接口,定义生成实例的方法
type ComputerBuilder interface {
// 添加中央处理器
AddCPU()
// 添加内存
AddMemory()
// 添加主板
AddMainboard()
// 添加硬盘
AddHardDisk()
// 添加显卡
AddGPU()
// 获取电脑主机实例
GetComputer() Computer
}
电脑主机基类(基础结构体)
// 电脑结构, 主要描述电脑有哪些重要组件,没有方法
type Computer struct {
CPU string
Memory string
Mainboard string
HardDisk string
GPU string
}
实现
接下来定义具体建造者
办公型电脑建造者OffceModelBuilder,实现了ComputerBuilder接口的所有方法
// 办公型电脑主机
type OffceModelBuilder struct {
Computer
}
// 实现ComputerBuilder的方法
func (om *OffceModelBuilder) AddCPU() {
om.CPU = "Intel-i3"
}
func (om *OffceModelBuilder) AddMemory() {
om.Memory = "8G"
}
func (om *OffceModelBuilder) AddMainboard() {
om.Mainboard = "B460"
}
func (om *OffceModelBuilder) AddHardDisk() {
om.HardDisk = "256G HDD"
}
func (om *OffceModelBuilder) AddGPU() {
om.GPU = "Intel HD630"
}
func (om *OffceModelBuilder) GetComputer() Computer {
return Computer{
CPU: om.CPU,
Memory: om.Memory,
Mainboard: om.Mainboard,
HardDisk: om.HardDisk,
GPU: om.GPU,
}
}
游戏型主机建造者GameModelBuilder,跟 OffceModelBuilder一样,都是实现ComputerBuilder的所有方法。但是其组装组件时用了更好的配置
// 游戏型电脑主机
type GameModelBuilder struct {
Computer
}
// 实现ComputerBuilder的方法
func (gm *GameModelBuilder) AddCPU() {
gm.CPU = "Intel-i9"
}
func (gm *GameModelBuilder) AddMemory() {
gm.Memory = "32G"
}
func (gm *GameModelBuilder) AddMainboard() {
gm.Mainboard = "X460"
}
func (gm *GameModelBuilder) AddHardDisk() {
gm.HardDisk = "512G SSD,1T HDD"
}
func (gm *GameModelBuilder) AddGPU() {
gm.GPU = "NVIDIA GTX3090"
}
func (gm *GameModelBuilder) GetComputer() Computer {
return Computer{
CPU: gm.CPU,
Memory: gm.Memory,
Mainboard: gm.Mainboard,
HardDisk: gm.HardDisk,
GPU: gm.GPU,
}
}
指挥者Director,包含一个ComputerBuilder类型,并定义了一个Builde方法。仔细看这里有用到Template Method模版方法的实现方式)
// 指挥者
type Director struct {
builder ComputerBuilder
}
// 建造方法,定义步骤及顺序(类似于Template Method模版模式)
func (d *Director) Build() Computer {
d.builder.AddCPU()
d.builder.AddMemory()
d.builder.AddMainboard()
d.builder.AddHardDisk()
d.builder.AddGPU()
return d.builder.GetComputer()
}
测试
func main() {
// 办公型电脑建造者
offceModelBuilder := &OffceModelBuilder{}
// 实例化一个指挥者,并传入具体建造者
director := Director{offceModelBuilder}
computer1 := director.Build()
fmt.Printf("办公型主机配置:%v \n", computer1)
// 游戏型电脑建造者
gameModelBuilder := &GameModelBuilder{}
// 这里直接赋值,也证明指挥者 Director不直接依赖具体建造者
director.builder = gameModelBuilder
computer2 := director.Build()
fmt.Printf("游戏型主机配置:%v \n", computer2)
}
运行结果
结果符合预期
代码已上传Github:LyonNee/design_patterns_with_go: 基于Golang实现的设计模式代码 (github.com)