两年前写过一篇PHP策略模式的文章,最近在做公司Go项目时也用到了策略模式,那就写一篇文章记录下来吧。

首先还是编写一个基类接口用于定义策略规范及实现逻辑方法

// MyBaseStrategy 策略公共接口
type MyBaseStrategy interface {
    MakeImplementation() (string, error)
}

接着声明好策略执行者,再编写一个策略生成的工厂类用于返回策略执行者的实现逻辑

// MyBaseOperator 策略执行者
type MyBaseOperator struct {
    // 嵌入策略接口,就不需要再声明实现方法了
    MyBaseStrategy
}

// NewMyOperator 策略执行者工厂方法
func NewMyOperator(strategy MyBaseStrategy) *MyBaseOperator {
    // 返回策略执行者,并将具体策略嵌入
    return &MyBaseOperator{strategy}
}

// GetOperatorByPlanName 通过计划名称获取策略执行者
func GetOperatorByPlanName(planName string) *MyBaseOperator {
    operator := NewMyOperator(map[string]MyBaseStrategy{
        "A": NewMyPlanAImplementationStrategy(),
    }[planName])
    return operator
}

最后编写具体策略实现

// MyPlanAImplementationStrategy A计划实现策略类
type MyPlanAImplementationStrategy struct {
}

// MakeImplementation A计划策略执行具体方法
func (plan *MyPlanAImplementationStrategy) MakeImplementation () (string, error) {
    return "This is my a plan class of implementation function", nil
}

// NewMyPlanAImplementationStrategy A计划实现策略类工厂方法
func NewMyPlanAImplementationStrategy() *MyPlanAImplementationStrategy {
    return &MyPlanAImplementationStrategy{}
}

调用策略的时候,就可以配合工厂类去动态生成策略实现类来执行逻辑

// 根据名称创建A计划执行者
thePlan := GetOperatorByPlanName("A")
// 执行A计划
result, err := thePlan.MakeImplementation()
// 有错误返回则抛出错误
if err != nil {
    panic(err)
}

fmt.Println(result)

这样就可以动态扩展多个策略,动态去调用某个具体策略去执行,起到最终程序解耦的效果,应用场景包括支付对接、计划执行等等。