什么是策略模式
策略模式可以让开发者定义一系列算法,并且将每种算法分别放入独立的类,从而使得算法的对象可以相互替换
组成;
- 上下文(Context): 维护指向具体策略引用的类,并且仅通过策略接口与该引用进行交流
- 策略(Stategy): 实现上下文所用算法的通用接口,它声明了一个上下文,用于执行策略的方法
- 具体策略(ConcreteStrategy):实现上下文所用算法的各种不同的变体的类。当上下文需要运行算法时,具体的策略会在其已连接的的策略对象上调用执行方法
- 客户端(Client): 创建一个特定策略的对象并将其传递给上下文,上下文会提供一个设置器,以便客户端在运行时替换相关联的策略
代码实现
package main
import "fmt"
// IStrategy 策略接口
type IStrategy interface {
Execute()
}
/*
定义具体策略类及其方法
具体策略类必须实现策略接口
*/
// strategyA 具体策略类
type strategyA struct {
}
func (a strategyA) Execute() {
fmt.Println("策略A")
}
// strategyB 具体策略类
type strategyB struct {
}
func (b strategyB) Execute() {
fmt.Println("策略B")
}
// NewStrategyA 创建具体策略类strategyA的新对象
func NewStrategyA() IStrategy {
return &strategyA{}
}
// NewStrategyB 创建具体策略类strategyB的新对象
func NewStrategyB() IStrategy {
return &strategyB{}
}
/*
定义上下文及其方法
上下文类中添加一个成员变量,用于存储对策略对象的引用
然后提供相应的设置器,用于修改成员变量
*/
// Context 上下文类
type Context struct {
strategy IStrategy
}
// SetStrategy 设置上下文对象执行的具体策略对象
func (c *Context) SetStrategy(strategy IStrategy) {
c.strategy = strategy
}
// Execute 上下文类的方法
func (c *Context) Execute() {
c.strategy.Execute()
}
func NewContext() *Context {
return &Context{}
}
func main() {
strategyB := NewStrategyB()
context := NewContext()
context.SetStrategy(strategyB)
context.Execute()
}
适用场景
- 需要使用对象中各种的不同的算法变体,并且希望能在运行时切换算法时,可以使用策略模式
- 有许多仅在执行某些行为时略有不同的相似类时,可以使用策略模式
优缺点
优点
- 部分算法可重用
- 子类化的代替方法
- 策略模式消除了条件语句
- 可以提供相同行为的不同实现
- 符合开闭原则
缺点
- 如果算法极少发生改变,则会让程序过于复杂
- 策略模式会让对象数量增加