主页

索引

模块索引

搜索页面

Strategy-策略模式

备注

allows one of a family of algorithms to be selected on-the-fly at runtime. Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. 需要使用策略模式,定义一些独立的类来封装不同的算法,每一个类封装一个具体的算法(即策略)。

工厂模式是解耦对象的创建和使用,观察者模式是解耦观察者和被观察者。策略模式跟两者类似,也能起到解耦的作用,不过,它解耦的是策略的定义、创建、使用这三部分。

策略模式包含一组可选策略,客户端代码一般是通过运行时动态确定使用哪种策略,这也是策略模式最典型的应用场景。这里的 “运行时动态” 指的是,我们事先并不知道会使用哪个策略,而是在程序运行期间,根据配置、用户输入、计算结果等这些不确定因素,动态决定使用哪种策略。

策略模式用来解耦策略的定义、创建、使用。实际上,一个完整的策略模式就是由这三个部分组成的:

1. 策略类的定义:
    比较简单,包含一个策略接口和一组实现这个接口的策略类。
2. 策略的创建:
    由工厂类来完成,封装策略创建的细节。
3. 策略模式的使用:
    包含一组策略可选,客户端代码如何选择使用哪个策略,有两种确定方法:
    编译时静态确定和运行时动态确定。
    其中,“运行时动态确定” 才是策略模式最典型的应用场景。

示例

package strategy

// 策略模式

// 定义一个策略类
type IStrategy interface {
  do(int, int) int
}

// 1. 策略实现:加
type add struct{}

func (*add) do(a, b int) int {
  return a + b
}

// 2. 策略实现:减
type reduce struct{}

func (*reduce) do(a, b int) int {
  return a - b
}

// 具体策略的执行者
type Operator struct {
  strategy IStrategy
}

// 设置策略
func (operator *Operator) setStrategy(strategy IStrategy) {
  operator.strategy = strategy
}

// 调用策略中的方法
func (operator *Operator) calculate(a, b int) int {
  return operator.strategy.do(a, b)
}

使用:

func TestStrategy(t *testing.T) {
  operator := Operator{}

  // 1. 
  operator.setStrategy(&add{})
  result := operator.calculate(1, 2)
  fmt.Println("add:", result)

  // 2. 
  operator.setStrategy(&reduce{})
  result = operator.calculate(2, 1)
  fmt.Println("reduce:", result)
}

实战

根据参数不同使用不同的认证策略(Basic 或 Bearer):

switch authHeader[0] {
case "Basic":
  operator.SetStrategy(a.basic)
case "Bearer":
  operator.SetStrategy(a.jwt)
  ...

主页

索引

模块索引

搜索页面