【Go-设计模式】策略模式 详解

概念:
定义一系列算法,让这些算法在运行时可以互换,使得分离算法,符合开闭原则。
定义 算法族(策略组),分别封装起来,让它们之间可以 互相替换,此模式让 算法的变化 独立于 使用算法的Client
这算法体现了几个设计原则:
- (1)把 变化的代码 从 不变的代码 中分离出来;
 - (2)针对 接口编程,而不是 具体类;
 - (3)多用 组合/聚合,少用 继承(Client通过 组合方式 使用策略)
 

UML:

- Context:
环境,持有一个 Strategy的引用 - Strategy:
抽象策略,定义 策略的具体功能实现 - ConcreteStrategy:
具体策略实现,抽象策略 约定的 相关算法 的 具体实现 
示例:
抽象的策略接口:
策略接口1:
type Strategy1 interface {
	OperationA()
}
策略接口2:
type Strategy2 interface {
	OperationB()
	OperationC()
}
具体的策略实现类:
策略实现类1:
type ConcreteStrategyI struct {
}
func (this ConcreteStrategyI) OperationA() {
	fmt.Println("策略1 实现的 OperationA")
}
策略实现类2:
type ConcreteStrategyII struct {
}
func (this ConcreteStrategyII) OperationA() {
	fmt.Println("策略2 实现的 OperationA")
}
策略实现类3:
type ConcreteStrategyIII struct {
}
func (this ConcreteStrategyIII) OperationB() {
	fmt.Println("策略3 实现的 OperationB")
}
func (this ConcreteStrategyIII) OperationC() {
	fmt.Println("策略3 实现的 OperationC")
}
策略实现类4:
type ConcreteStrategyIV struct {
}
func (this ConcreteStrategyIV) OperationB() {
	fmt.Println("策略4 实现的 OperationB")
}
func (this ConcreteStrategyIV) OperationC() {
	fmt.Println("策略4 实现的 OperationC")
}
实体类:
type Model struct {
	strategyI  Strategy1
	strategyII Strategy2
	otherAttr  string
}
func (this Model) DoSomething() {
	fmt.Print("执行策略1时:")
	this.strategyI.OperationA()
	fmt.Print("执行策略2时:")
	this.strategyII.OperationC()
	this.strategyII.OperationB()
	fmt.Printf("其他操作:%v", this.otherAttr)
}
func NewModel(strategy1 Strategy1, strategy2 Strategy2, attr string) Model {
	return Model{
		strategyI:  strategy1,
		strategyII: strategy2,
		otherAttr:  attr,
	}
}
测试:
package main
import (
	"DemoProject/design/base23/strategy" // 根据自己的项目路径定制
	"fmt"
)
func main() {
	// strategy
	model1 := strategy.NewModel(strategy.ConcreteStrategyI{}, strategy.ConcreteStrategyIII{}, "收尾工作1")
	model1.DoSomething()
	fmt.Println("=========================================")
	model2 := strategy.NewModel(strategy.ConcreteStrategyII{}, strategy.ConcreteStrategyIV{}, "收尾工作2")
	model2.DoSomething()
}
注意事项:
关键:分析项目中 变化部分 与 不变部分
核心思想:
- 多用 组合/聚合,少用 继承
 - 用 行为类组合,而不是 行为的继承
 
体现了 “对修改关闭,对扩展开放” 原则,
Client 增加行为 不用 修改原有代码,只要 添加一种策略(或者行为) 即可,避免了使用 多重转移语句(if..else if..else)
提供了 可以替换继承关系 的办法:
策略模式 将 算法 封装在 独立的 Strategy 类 中,使得用户可以 独立于其 Context 改变它,使它 易于切换、易于理解、易于扩展
需要注意的是:每添加一个策略 就要 增加一个类,当 策略过多 是会导致 类数目庞大
本例中的示例可能看起来很像其实此处非常像 模板方法模式 和 组合模式,如果区分不清的同学,可以参考这篇博文:
《Go 策略模式讲解和代码示例》
其中运用到的 缓存过期算法 就采用了 策略模式 进行的实现
例子相对更加清晰直观

                
            
浙公网安备 33010602011771号