Skip to content

策略模式

概念

  • 策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法
  • 比如每个人都要交“个人所得税”,但是在美国交个人所得税和在中国交个人所得税是有不同的算法,所以就要有不同的策略
  • 策略模式是一种对象行为型模式

结构

Image title

策略模式结构图

代码示例

  • strategy.go

    package strategy
    
    import "fmt"
    
    // 实现一个上下文类
    type Context struct {
        Strategy
    }
    
    // 抽象的策略
    type Strategy interface {
        Do()
    }
    
    // 实现具体的策略:策略1
    type Strategy1 struct {
    }
    
    func (s1 Strategy1) Do() {
        fmt.Println("执行策略1")
    }
    
    // 实现具体的策略:策略2
    type Strategy2 struct {
    }
    
    func (s2 Strategy2) Do() {
        fmt.Println("执行策略2")
    }
    

  • strategy_test.go

    package strategy
    
    import "testing"
    
    func TestStrategy_Do(t *testing.T) {
        context := Context{}
        strategy1 := &Strategy1{}
        context.Strategy = strategy1
        context.Do()
    
    
        strategy2 := &Strategy2{}
        context.Strategy = strategy2
        context.Do()
    }
    
    
    // 执行输出
    === RUN   TestStrategy_Do
    执行策略1
    执行策略2
    --- PASS: TestStrategy_Do (0.00s)
    PASS
    
    Process finished with the exit code 0
    

实战模拟

  • 实现一个日志记录器:文件记录和数据库记录两种
  • logger.go

    package logger
    
    import "fmt"
    
    // 实现一个日志记录器(相当于context)
    type LogManager struct {
        logging
    }
    
    func NewLogManager(logging logging) *LogManager {
        return &LogManager{logging}
    }
    
    // 抽象的日志
    type logging interface {
        Info()
        Error()
    }
    
    // 实现具体的日志:文件记录的方式
    type FileLogging struct {
    }
    
    func (fl *FileLogging) Info() {
        fmt.Println("文件记录Info")
    }
    
    func (fl *FileLogging) Error() {
        fmt.Println("文件记录Error")
    }
    
    // 实现具体的日志:数据库记录的方式
    type DbLogging struct {
    }
    
    func (dl *DbLogging) Info() {
        fmt.Println("数据库记录Info")
    }
    
    func (dl *DbLogging) Error() {
        fmt.Println("数据库记录Error")
    }
    

  • logger_test.go

    package logger
    
    import "testing"
    
    func TestNewLogManager(t *testing.T) {
        fileLogging := &FileLogging{}
        logManager := NewLogManager(fileLogging)
        logManager.Info()
        logManager.Error()
    
        dbLogging := &DbLogging{}
        logManager.logging = dbLogging
        logManager.Info()
        logManager.Error()
    }
    
    
    // 输出
    === RUN   TestNewLogManager
    文件记录Info
    文件记录Error
    数据库记录Info
    数据库记录Error
    --- PASS: TestNewLogManager (0.00s)
    PASS
    
    Process finished with the exit code 0
    

策略模式总结

  • 优点:对“开闭原则”的完美支持
  • 缺点:客户端必须知道所有策略类,并自己决定使用哪一个策略类
  • 适合场景:一个系统需要动态的在几种算法或行为中选择一种