Golang学习笔记_36——装饰器模式
Golang学习笔记_37——外观模式
Golang学习笔记_38——享元模式
文章目录
- 一、核心概念
- 1. 定义
- 2. 解决的问题
- 3. 核心角色
- 4. 类图
- 二、特点分析
- 三、适用场景
- 1. 支付系统
- 2. 数据压缩
- 3. 游戏AI
- 4. 折扣计算
- 四、代码示例(Go语言)
- 场景:电商会员折扣系统
- 执行结果
- 五、高级应用
- 1. 策略工厂模式
- 2. 组合策略
- 六、与其他模式对比
- 七、总结
一、核心概念
1. 定义
策略模式是一种行为型设计模式,通过定义一系列可互换的算法,并将其封装为独立类,使得算法可以独立于客户端而变化。核心思想是将算法与使用场景解耦,支持运行时动态切换策略。
2. 解决的问题
- 算法频繁切换:需要根据不同条件选择不同算法(如支付方式、折扣策略)
- 消除条件判断:避免大量
if-else
或switch-case
语句 - 算法复用性:同一算法被多个客户端调用(如排序、压缩算法)
3. 核心角色
角色 | 作用 |
---|---|
Strategy | 策略接口,定义算法的公共方法(如Execute() ) |
ConcreteStrategy | 具体策略实现类(如支付宝支付、微信支付) |
Context | 上下文类,持有策略引用并执行算法 |
4. 类图
策略模式类图" />
@startuml
class Context {- strategy: Strategy+ SetStrategy()+ ExecuteStrategy()
}interface Strategy {+ Execute()
}class ConcreteStrategyA {+ Execute()
}class ConcreteStrategyB {+ Execute()
}Context o--> Strategy
Strategy <|.. ConcreteStrategyA
Strategy <|.. ConcreteStrategyB
@enduml
二、特点分析
优点
- 开闭原则:新增策略无需修改现有代码
- 代码清晰:消除复杂条件判断,提升可维护性
- 灵活扩展:运行时动态切换策略(如游戏AI行为切换)
缺点
- 类数量膨胀:每个策略需单独定义类
- 客户端耦合:客户端需了解所有策略的存在
三、适用场景
1. 支付系统
- 策略接口:
PaymentStrategy
- 具体策略:信用卡、支付宝、微信支付
- 动态切换:用户下单时选择支付方式
// 策略接口
type PaymentStrategy interface {Pay(amount float64) string
}// 具体策略:支付宝
type AlipayStrategy struct{}
func (a *AlipayStrategy) Pay(amount float64) string {return fmt.Sprintf("支付宝支付%.2f元", amount)
}
2. 数据压缩
- 策略接口:
CompressionStrategy
- 具体策略:ZIP、RAR、7z算法
- 按需选择:根据文件类型自动选择压缩算法
// 策略接口
type CompressionStrategy interface {Compress(file string) []byte
}// 具体策略:ZIP压缩
type ZipStrategy struct{}
func (z *ZipStrategy) Compress(file string) []byte {return []byte("ZIP压缩后的数据")
}
3. 游戏AI
- 策略接口:
AIBehavior
- 具体策略:进攻、防御、逃跑模式
- 动态调整:根据玩家血量切换NPC行为
// 策略接口
type AIBehavior interface {Act() string
}// 具体策略:防御模式
type DefenseBehavior struct{}
func (d *DefenseBehavior) Act() string {return "进入防御状态"
}
4. 折扣计算
- 策略接口:
DiscountStrategy
- 具体策略:普通用户9折、VIP用户8折
- 组合策略:叠加满减和折扣(见高级应用)
四、代码示例(Go语言)
场景:电商会员折扣系统
package strategydemo// 策略接口
type DiscountStrategy interface {Calculate(price float64) float64
}// 具体策略:普通会员
type NormalDiscount struct{}
func (n *NormalDiscount) Calculate(price float64) float64 {return price * 0.9 // 9折
}// 具体策略:VIP会员
type VIPDiscount struct{}
func (v *VIPDiscount) Calculate(price float64) float64 {return price * 0.8 // 8折
}// 上下文类
type Order struct {strategy DiscountStrategy
}func (o *Order) SetStrategy(s DiscountStrategy) {o.strategy = s
}func (o *Order) Checkout(price float64) float64 {return o.strategy.Calculate(price)
}// 客户端使用
func TestStrategy() {order := &Order{}// 普通用户order.SetStrategy(&NormalDiscount{})fmt.Printf("普通用户价格: %.2f\n", order.Checkout(100)) // 90.00// 切换为VIP策略order.SetStrategy(&VIPDiscount{})fmt.Printf("VIP用户价格: %.2f\n", order.Checkout(100)) // 80.00
}
执行结果
=== RUN Test_TestStrategy
普通用户价格: 90.00
VIP用户价格: 80.00
--- PASS: Test_TestStrategy (0.00s)
PASS
五、高级应用
1. 策略工厂模式
// 策略工厂(带注册机制)
type StrategyFactory struct {strategies map[string]DiscountStrategy
}func NewStrategyFactory() *StrategyFactory {return &StrategyFactory{strategies: map[string]DiscountStrategy{"normal": &NormalDiscount{},"vip": &VIPDiscount{},},}
}// 动态获取策略
func (f *StrategyFactory) GetStrategy(key string) DiscountStrategy {return f.strategies[key]
}// 使用示例
factory := NewStrategyFactory()
order.SetStrategy(factory.GetStrategy("vip"))
2. 组合策略
// 组合折扣(满300减50 + VIP折扣)
type CompositeDiscount struct {strategies []DiscountStrategy
}func (c *CompositeDiscount) Calculate(price float64) float64 {for _, s := range c.strategies {price = s.Calculate(price)}return price
}// 使用示例
composite := &CompositeDiscount{strategies: []DiscountStrategy{&FullReductionStrategy{Threshold: 300, Reduce: 50},&VIPDiscount{},},
}
fmt.Printf("组合折扣价格: %.2f", composite.Calculate(350)) // (350-50)*0.8=240
六、与其他模式对比
模式 | 核心目标 | 关键区别 |
---|---|---|
状态模式 | 对象内部状态改变行为 | 状态转移由内部条件触发 |
工厂模式 | 创建对象 | 关注对象创建过程 |
模板方法 | 算法步骤固定 | 通过继承实现代码复用 |
七、总结
策略模式通过算法封装和动态切换,解决了以下问题:
- 灵活扩展:新增策略无需修改上下文
- 代码复用:相同策略可被多个客户端共享
- 条件简化:消除复杂的
if-else
分支
在Go语言中实现时需注意:
- 通过接口实现多态,而非继承
- 使用工厂模式管理策略实例
- 组合策略实现复杂算法叠加
- 避免策略类过度细分(如差异过小的策略合并)