策略模式在golang工程中的应用实践

111 阅读2分钟

背景

以商城订单处理为例,针对不同订单,需要采取不同的策略。

  • 买菜的订单,需要整合订单信息,分配调度任务给不同的仓库
  • 拼单,需要等待拼单完成,下发订单给对应商家
  • 正常订单,在下单完成后,无需等待,直接下发给商家

策略模式可以将一系列算法封装起来,对算法进行编排,满足某一个功能的多种策略需求

策略模式优点

  • 可以避免多重条件判断
  • 公共代码的可复用性更强
  • 本身符合开闭原则
  • 能更好的适配上下文比较多的场景

策略模式缺点

  • 需要使用者了解不同策略之间的区别
  • 会产生多个策略类

具体实现

未命名绘图.png

未命名绘图.png

  • 抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
  • 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
  • 环境(Context)类:持有一个策略类的引用,最终给客户端调用。

demo

以上述订单处理为例

策略类


type OrderStrategy interface {
	Handle(ctx context.Context) error
}

买菜订单处理类

type VegeOrderStrategy struct {
	City    string
	OrderID string
}

func (s *VegeOrderStrategy) Handle(ctx context.Context) error {
	// pre handle
	// order allocate
	// order distribute
	// after handle, msg notify
	return nil
}

拼单订单处理类


type SpliceOrderStrategy struct {
	Sum     int
	OrderID string
}

func (s *SpliceOrderStrategy) Handle(ctx context.Context) error {
	// pre handle
	// wait notify
	// distribute
	// after handle, msg notify
	return nil
}

正常订单处理类

type NormalOrderStrategy struct {
	OrderID string
}

func (s *NormalOrderStrategy) Handle(ctx context.Context) error {
	// pre handle
	// order distribute
	// check confirm
	// after handle, msg notify
	return nil
}

上下文

type OrderContext struct {
	OrderStrategy OrderStrategy
}

func (c *OrderContext) Handle(ctx context.Context) error {
	return c.OrderStrategy.Handle(ctx)
}

main.go

func main() {
	VegeOrderStrategy := &VegeOrderStrategy{
		City:    "Beijing",
		OrderID: "123456",
	}
	handler := &OrderContext{
		OrderStrategy: VegeOrderStrategy,
	}
	handler.Handle(context.Background())
}