Golang学习笔记_27——单例模式
Golang学习笔记_28——工厂方法模式
Golang学习笔记_29——抽象工厂模式
文章目录
- 一、建造者模式核心概念
- 1. 定义
- 2. 解决的问题
- 3. 核心角色
- 4. 类图(与下方示例一致)
- 二、建造者模式的特点
- 三、适用场景
- 1. 构造复杂对象
- 2. 构造过程需要灵活控制
- 3. 避免构造函数参数爆炸
- 4. 需要生成不同表示的对象
- 四、与其他创建型模式的对比
- 五、Go 语言代码示例
- 六、建造者模式的高级用法
- 1. 链式调用
- 2. 可选构造步骤
- 3. 参数校验
- 4. 演示
- 七、总结
一、建造者模式核心概念
1. 定义
建造者模式是一种 创建型设计模式,用于 分步骤构造复杂对象。它将对象的构造过程与其表示分离,使得同样的构造过程可以创建不同的表示。
2. 解决的问题
- 复杂对象的构造逻辑混乱:当一个对象需要多个步骤或参数才能构造完成时,直接通过构造函数或工厂方法会导致参数爆炸(如构造函数参数过多)。
- 构造过程需要灵活控制:例如,某些场景需要跳过某些构造步骤,或改变步骤顺序。
3. 核心角色
- Director(指挥者):负责调用建造者的步骤方法,控制构造流程。
- Builder(抽象建造者):定义构造对象的步骤接口(如
BuildPartA()
,BuildPartB()
)。 - ConcreteBuilder(具体建造者):实现 Builder 接口,提供具体构造逻辑,并返回最终结果。
- Product(产品):最终要构造的复杂对象。
4. 类图(与下方示例一致)
二、建造者模式的特点
优点
-
分步构造复杂对象
将复杂对象的构造过程拆解为多个步骤,代码更清晰。 -
复用构造过程
通过不同的ConcreteBuilder
,可以用相同的构造逻辑生成不同的对象表示。 -
隐藏产品细节
客户端不需要知道产品的内部组成和构造细节。 -
灵活控制构造流程
Director
可以灵活调整构造步骤(例如跳过某些步骤)。
缺点
-
代码复杂度增加
需要定义多个类(Builder、Director、Product),对简单对象可能过度设计。 -
产品需高度一致
如果产品之间的差异极大,建造者模式可能不适用(需频繁修改 Builder 接口)。
三、适用场景
1. 构造复杂对象
- 对象需要多个步骤或组件组合而成。
- 示例:构造一个包含 CPU、内存、硬盘的电脑配置。
2. 构造过程需要灵活控制
- 构造步骤的顺序或内容需要动态调整。
- 示例:生成不同格式的报告(HTML/PDF),步骤相同但实现不同。
3. 避免构造函数参数爆炸
- 当构造函数参数过多时(如超过 4 个),使用建造者模式更清晰。
- 示例:创建用户对象(姓名、年龄、地址、电话、邮箱等)。
4. 需要生成不同表示的对象
- 同一构造过程需要生成不同表现形式的结果。
- 示例:同一数据源生成表格、图表、文本三种展示形式。
四、与其他创建型模式的对比
模式 | 核心目标 | 关键区别 |
---|---|---|
工厂方法 | 创建单一对象 | 直接返回完整对象,不涉及分步构造。 |
抽象工厂 | 创建产品族(多个相关对象) | 关注产品家族的兼容性,而非分步构造。 |
建造者 | 分步骤构造复杂对象 | 强调构造过程的控制和步骤拆分。 |
原型 | 通过克隆生成对象 | 避免重复初始化,直接复制现有对象。 |
五、Go 语言代码示例
场景描述
构造一台电脑(Computer
),包含 CPU、内存、硬盘等组件,支持不同配置(游戏电脑、办公电脑)。
代码实现
package builder_demoimport "fmt"// product
type Computer struct {CPU stringMemory stringHardDisk string
}func (c Computer) show() {fmt.Printf("电脑配置:\n CPU: %s\n 内存: %s\n 硬盘: %s\n\n", c.CPU, c.Memory, c.HardDisk)
}// Builder Interface
type ComputerBuilder interface {buildCPU() ComputerBuilderbuildMemory() ComputerBuilderbuildHardDisk() ComputerBuilderbuild() Computer
}// ConcreteBuilder
type GamingComputerBuilder struct {computer Computer
}func (g *GamingComputerBuilder) buildCPU() ComputerBuilder {g.computer.CPU = "Intel i9"return g
}func (g *GamingComputerBuilder) buildMemory() ComputerBuilder {g.computer.Memory = "32G"return g
}func (g *GamingComputerBuilder) buildHardDisk() ComputerBuilder {g.computer.HardDisk = "512G SSD"return g
}func (g *GamingComputerBuilder) build() Computer {return g.computer
}// ConcreteBuilder
type OfficeComputerBuilder struct {computer Computer
}func (o *OfficeComputerBuilder) buildCPU() ComputerBuilder {o.computer.CPU = "Intel i7"return o
}func (o *OfficeComputerBuilder) buildMemory() ComputerBuilder {o.computer.Memory = "16G"return o
}func (o *OfficeComputerBuilder) buildHardDisk() ComputerBuilder {o.computer.HardDisk = "1T HDD"return o
}
func (o *OfficeComputerBuilder) build() Computer {return o.computer
}// Director
type Director struct {builder ComputerBuilder
}func (d *Director) Construct() Computer {return d.builder.buildCPU().buildMemory().buildHardDisk().build()
}func test() {// 组装游戏电脑director := Director{}gamingComputerBuilder := &GamingComputerBuilder{}director.builder = gamingComputerBuilderdirector.Construct().show()// 组装办公电脑director.builder = &OfficeComputerBuilder{}director.Construct().show()}
输出结果
=== RUN Test_test
电脑配置:CPU: Intel i9内存: 32G硬盘: 512G SSD电脑配置:CPU: Intel i7内存: 16G硬盘: 1T HDD--- PASS: Test_test (0.00s)
PASS
六、建造者模式的高级用法
1. 链式调用
通过返回 Builder
自身实现链式调用(如上述代码中的 SetCPU().SetMemory()
)。
2. 可选构造步骤
在 Director
中动态决定是否执行某些步骤:
func (d *Director) Construct(needDisk bool) Computer {builder := d.builder.SetCPU().SetMemory()if needDisk {builder = builder.SetDisk()}return builder.Build()
}
3. 参数校验
在 Build()
方法中校验参数合法性:
func (b *GamingComputerBuilder) Build() Computer {if b.computer.CPU == "" {panic("CPU 未配置!")}return b.computer
}
4. 演示
package builder_demoimport "fmt"// Order 订单对象
type Order struct {UserID stringItems []stringAddress stringCoupon stringNotes string
}// Print 打印订单信息
func (o *Order) Print() {fmt.Printf("订单详情:\n"+" 用户ID: %s\n"+" 商品: %v\n"+" 地址: %s\n"+" 优惠券: %s\n"+" 备注: %s\n",o.UserID, o.Items, o.Address, o.Coupon, o.Notes)
}// OrderBuilder Builder 订单建造者
type OrderBuilder struct {order Order
}// SetUserID 链式方法: 设置用户ID
func (b *OrderBuilder) SetUserID(userID string) *OrderBuilder {b.order.UserID = userIDreturn b
}// AddItem 链式方法: 添加商品
func (b *OrderBuilder) AddItem(item string) *OrderBuilder {b.order.Items = append(b.order.Items, item)return b
}// SetAddress 链式方法: 设置地址
func (b *OrderBuilder) SetAddress(address string) *OrderBuilder {b.order.Address = addressreturn b
}// SetCoupon 链式方法: 设置优惠券
func (b *OrderBuilder) SetCoupon(coupon string) *OrderBuilder {b.order.Coupon = couponreturn b
}// SetNotes 链式方法: 设置备注
func (b *OrderBuilder) SetNotes(notes string) *OrderBuilder {b.order.Notes = notesreturn b
}// Build 链式方法: 构建订单
func (b *OrderBuilder) Build() Order {// 信息校验if b.order.UserID == "" {panic("用户ID不能为空")}if len(b.order.Items) == 0 {panic("商品不能为空")}return b.order
}func test2() {builder := OrderBuilder{}order := builder.SetUserID("123456").AddItem("商品1").AddItem("商品2").SetAddress("北京市朝阳区").SetCoupon("满100减20").SetNotes("备注信息").Build()order.Print()
}
输出结果
=== RUN Test_test2
订单详情:用户ID: 123456商品: [商品1 商品2]地址: 北京市朝阳区优惠券: 满100减20备注: 备注信息
--- PASS: Test_test2 (0.00s)
PASS
七、总结
建造者模式通过 分步骤构造对象 和 隔离构造逻辑,解决了复杂对象创建的灵活性问题。适用于以下场景:
- 对象构造过程复杂,涉及多个步骤。
- 需要生成不同表示的对象。
- 避免构造函数参数过多。
结合链式调用、参数校验等技巧,可以进一步提升代码的可读性和健壮性。如果需要更具体的扩展场景(如结合工厂模式),可以告诉我! 🚀