上篇文章我给我们分享了规划形式中的模版形式,给我们讲了用模版形式在项目开发时提炼流程、减少重复开发的技巧。同时,在上一篇文章我也分享了我总结的一个暴论,那便是“模板、战略和责任链三个规划形式是解决事务系统流程杂乱多变这个痛点的利器”。

今日我们继续接着一同学习一下战略形式,以及用 Go 代码怎样完结战略形式。

什么是战略形式

战略形式是一种行为规划形式,经过战略形式,能够在运转时修正一个目标的行为。很多资料里对它的界说是:

界说一类算法族,将每个算法别离封装起来,让他们能够相互替换,此形式让算法的变化独立于运用算法的客户端。

看完战略形式这个界说,你是不是也有一种看了等于没看的感觉,我一开始看的时分也是这样,下面我再用一些大文言给我们解释一下。

文言战略形式

战略形式这个界说乍一看起来,仍是挺笼统、挺难懂的,这儿说的算法并不是我们想找作业预备面试时每天要刷的那种算法;界说一类算法族中的算法族说的要完结的某项使命的归类,举个比方来说比方用户付出,便是个使命类。

算法族中的每个算法(即战略)则是说的完结这项使命的详细办法,结合我们的比方来说便是能够用付出宝也能够用微信付出这两种办法 (算法) ,来完结我们界说的用户付出这项使命 (算法族)。

战略形式主要用于允许我们的程序在运转时动态更改一个使命的处理逻辑,常见的运用场景有针对软件用户群体的不同战略切换(用一个烂大街的词儿表达便是千人千面)和事务流程兜底切换。

留意:这儿是为了我们好了解举了付出这个比方,实际上运转时切换付出办法仍是挺杂乱的,实践的时分你能够先从运转时切换通知用户的使命练起。

战略形式要解决的问题是,让运用客户端跟详细履行使命的战略解耦,不论运用哪种战略完结使命,不需求更改客户端运用战略的办法。

上面说的这些运用战略形式完结使命的整个形态用 UML 图表示出来,会比较清晰,战略形式的 UML 图如下:

Go 程序里 if else 分支太多?试着用策略模式治理一下吧

图中,主要有四类角色:

  • 客户端:这个客户端能够简略了解成是建议使命调用的代码。
  • 笼统战略:便是上面界说中的算法族,是一切详细战略的通用接口,声明了用于履行完结使命的办法。
  • 详细战略:完结了笼统战略,界说了详细应该怎样完结使命。
  • 上下文:作为客户端和详细战略的中间层,达到客户端与详细战略解耦的作用,它保护指向详细战略的引证,且仅经过笼统战略中界说的接口与详细战略进行交流。常用的完结办法是经过组合

上面类图里一个细节,上下文目标引证详细战略类的时分,运用的是组合的办法,让其私有特点指向战略接口的详细完结,这样就能完结在运转时修正履行使命的详细战略的作用(经过SetStrategy办法)。

光看上面的描述和UML图,仍是有点单薄,为了更简单了解,下面我们再举个更详细点的比方。

战略形式示例–完结付出战略

举例环节,接着用我们上面用的用户付出这个使命为比方。比方说在购物 App 上买东西后要付钱,客户端运用微信付出、或者是其他三方在线付出。假如运用战略形式进行解耦,客户端都能够运用同样的调用办法完结付出,甚至能够在微信付出不能运用时,让运用无痛地切换到三方付出,来完结付出。

留意这儿的客户端是上面说的,调用上下文的代码,不是手机APP。

在用代码完结付出战略前,先用 UML 类图整理一下整个完结的大体结构:

Go 程序里 if else 分支太多?试着用策略模式治理一下吧

  • PayBehavior:笼统战略,对付出使命进行接口笼统
  • WxPay 和 ThirdPay :是详细的战略完结
  • PaxCtx:上下文目标在这儿有两个作用,第一是和谐自己持有的 PayBehavior 详细完结,完结付出的使命,第二是保护建议付出需求的付出参数–即图中的私有特点payParams

下面我们把这个 UML 图转化为代码完结,首先是界说PayBehavior 战略的接口

type PayBehavior interface {
 OrderPay(px *PayCtx)
}

有了接口后,我们来界说两个战略的完结

// 详细付出战略完结
// 微信付出
"本文运用的完好可运转源码
去大众号「网管叨bi叨」发送【规划形式】即可收取"
type WxPay struct {}
func(*WxPay) OrderPay(px *PayCtx) {
 fmt.Printf("Wx付出加工付出请求 %v\n", px.payParams)
 fmt.Println("正在运用Wx付出进行付出")
}
// 三方付出
type ThirdPay struct {}
func(*ThirdPay) OrderPay(px *PayCtx) {
 fmt.Printf("三方付出加工付出请求 %v\n", px.payParams)
 fmt.Println("正在运用三方付出进行付出")
}

有了战略的完结后,还得有个上下文来和谐它们,以及持有完结这个使命所必需的那些入参payParams

"本文运用的完好可运转源码
去大众号「网管叨bi叨」发送【规划形式】即可收取"
type PayCtx struct {
 // 提供付出能力的接口完结
 payBehavior PayBehavior
 // 付出参数
 payParams map[string]interface{}
}
func (px *PayCtx) setPayBehavior(p PayBehavior) {
 px.payBehavior = p
}
func (px *PayCtx) Pay() {
 px.payBehavior.OrderPay(px)
}
func NewPayCtx(p PayBehavior) *PayCtx {
 // 付出参数,Mock数据
 params := map[string]interface{} {
  "appId": "234fdfdngj4",
  "mchId": 123456,
 }
 return &PayCtx{
  payBehavior: p,
  payParams: params,
 }
}

一切这些代码都预备好后,我们就能够试着运转程序调用它们了。

func main() {
 wxPay := &WxPay{}
 px := NewPayCtx(wxPay)
 px.Pay()
 // 假设现在发现微信付出没钱,改用三方付出进行付出
 thPay := &ThirdPay{}
 px.setPayBehavior(thPay)
 px.Pay()
}

这个比方的完结仍是比较简略的,信任我们都能看懂,我觉得最重要的是了解这个代码框架,后面自己结合实际在项目里完结战略形式的时分,能够支持拿来套用。

本文的完好源码,现已同步录入到我整理的电子教程里啦,可向我的大众号「网管叨bi叨」发送关键字【规划形式】收取。

Go 程序里 if else 分支太多?试着用策略模式治理一下吧

下面我们再来说说战略形式和上篇文章学习的模板形式的区别和相关运用。

战略形式和模板形式

战略形式和模版形式常常配合运用,战略形式是让完结某个使命的详细办法能够相互切换,而模版形式则是针对一个流程的共性整理出固定的履行步骤,详细步骤的履行办法下放给子类来完结。两者解耦的维度不一样,战略形式在笼统办法的完结里,常常会用到模板形式。

仍是拿我们上面的付出行为举比方。上面战略形式界说了一个算法族(付出),以及多个详细算法完结(微信、三方付出),让付出战略对客户端解耦。

上面我们的示例代码仍是比较简略的,一般完结付出时,还需求用参数生成签名、验证客户端传过来的签名、调用付出基础服务进行预下单、下单等操作,但是每种付出基础服务规划的接口和交互流程可能会有些小的不同,这个时分就能够用上签论理学的模版形式,统一付出使命内部的流程步骤,战略形式、模版形式相结合运用能让我们写的程序更健壮、更简单保护。

最终

好了今日的文章就到这儿了,假如你也想让自己写出更好的代码,想用规划形式解决开发中的痛点,请继续关注后面这个系列的更新,觉得文章不错就动动手点个在看和赞吧,我们下期再见。