嗯,个人代码没有
else
系列,一个设计模式业务真实使用的golang系列。
本系列主要分享,如何在咱们的真实业务场景中使用设计模式。git
本系列文章主要采用以下结构:github
本文主要介绍「策略模式」如何在真实业务场景中使用。golang
「策略模式」比较简单,你们日常工做中应该常常使用到,因此本文做为复习,帮助你们温故知新。咱们先来看下定义:算法
不一样的算法按照统一的标准封装,客户端根据不一样的场景,决策使用何种算法。
上面的概念的关键词:sql
概念很容易理解,很少说。json
「策略模式」的优点:segmentfault
每一行代码下面的十字路口
当代码的下一步面临选择的时候均可以使用「策略模式」,咱们把不一样选择的算法按照统一的标准封装,获得一类算法集的过程,就是实现「策略模式」的过程。设计模式
咱们有哪些真实业务场景能够用「策略模式」呢?
好比:缓存
本文以支付接口举例,说明「策略模式」的具体使用。微信
关于怎么用,彻底能够生搬硬套我总结的使用设计模式的四个步骤:
咱们以某团的订单支付页面为例,页面上的每个支付选项都是一个支付策略。以下:
用户可使用:
用户决定使用美团支付下的银行卡支付方式的参数
用户决定使用支付宝网页版支付方式的参数
注:不必定彻底准确。
咱们经过梳理的文本业务流程获得了以下的业务流程图:
注:流程不必定彻底准确。
「策略模式」的核心是接口:
PaymentInterface
Pay(ctx *Context) error
当前支付方式的支付逻辑Refund(ctx *Context) error
当前支付方式的退款逻辑伪代码以下:
// 定义一个支付接口 - `PaymentInterface` + 抽象方法`Pay(ctx *Context) error`: 当前支付方式的支付逻辑 + 抽象方法`Refund(ctx *Context) error`: 当前支付方式的退款逻辑 // 定义具体的支付方式 实现接口`PaymentInterface` - 具体的微信支付方式`WechatPay` + 实现方法`Pay`: 支付逻辑 + 实现方法`Refund`: 支付逻辑 - 具体的支付宝支付网页版方式`AliPayWap` + 实现方法`Pay`: 支付逻辑 + 实现方法`Refund`: 支付逻辑 - 具体的支付宝支付网页版方式`BankPay` + 实现方法`Pay`: 支付逻辑 + 实现方法`Refund`: 支付逻辑 // 客户端代码 经过接口参数pay_type的值判断是哪一种支付方式策略
同时获得了咱们的UML图:
package main import ( "fmt" "runtime" ) //------------------------------------------------------------ //个人代码没有`else`系列 //策略模式 //@auhtor TIGERB<https://github.com/TIGERB> //------------------------------------------------------------ const ( // ConstWechatPay 微信支付 ConstWechatPay = "wechat_pay" // ConstAliPayWap 支付宝支付 网页版 ConstAliPayWap = "AliPayWapwap" // ConstBankPay 银行卡支付 ConstBankPay = "quickbank" ) // Context 上下文 type Context struct { // 用户选择的支付方式 PayType string `json:"pay_type"` } // PaymentInterface 支付方式接口 type PaymentInterface interface { Pay(ctx *Context) error // 支付 Refund(ctx *Context) error // 退款 } // WechatPay 微信支付 type WechatPay struct { } // Pay 当前支付方式的支付逻辑 func (p *WechatPay) Pay(ctx *Context) (err error) { // 当前策略的业务逻辑写这 fmt.Println(runFuncName(), "使用微信支付...") return } // Refund 当前支付方式的支付逻辑 func (p *WechatPay) Refund(ctx *Context) (err error) { // 当前策略的业务逻辑写这 fmt.Println(runFuncName(), "使用微信退款...") return } // AliPayWap 支付宝网页版 type AliPayWap struct { } // Pay 当前支付方式的支付逻辑 func (p *AliPayWap) Pay(ctx *Context) (err error) { // 当前策略的业务逻辑写这 fmt.Println(runFuncName(), "使用支付宝网页版支付...") return } // Refund 当前支付方式的支付逻辑 func (p *AliPayWap) Refund(ctx *Context) (err error) { // 当前策略的业务逻辑写这 fmt.Println(runFuncName(), "使用支付宝网页版退款...") return } // BankPay 银行卡支付 type BankPay struct { } // Pay 当前支付方式的支付逻辑 func (p *BankPay) Pay(ctx *Context) (err error) { // 当前策略的业务逻辑写这 fmt.Println(runFuncName(), "使用银行卡支付...") return } // Refund 当前支付方式的支付逻辑 func (p *BankPay) Refund(ctx *Context) (err error) { // 当前策略的业务逻辑写这 fmt.Println(runFuncName(), "使用银行卡退款...") return } // 获取正在运行的函数名 func runFuncName() string { pc := make([]uintptr, 1) runtime.Callers(2, pc) f := runtime.FuncForPC(pc[0]) return f.Name() } func main() { // 相对于被调用的支付策略 这里就是支付策略的客户端 // 业务上下文 ctx := &Context{ PayType: "wechat_pay", } // 获取支付方式 var instance PaymentInterface switch ctx.PayType { case ConstWechatPay: instance = &WechatPay{} case ConstAliPayWap: instance = &AliPayWap{} case ConstBankPay: instance = &BankPay{} default: panic("无效的支付方式") } // 支付 instance.Pay(ctx) }
代码运行结果:
[Running] go run "../easy-tips/go/src/patterns/strategy/strategy.go" main.(*WechatPay).Pay 使用微信支付...
最后总结下,「策略模式」抽象过程的核心是:
在每一行代码下面的十字路口
interface
interface
封装分支代码,获得每个具体策略特别说明: 1. 个人代码没有`else`,只是一个在代码合理设计的状况下天然而然无限接近或者达到的结果,并非一个硬性的目标,务必较真。 2. 本系列的一些设计模式的概念可能和原概念存在差别,由于会结合实际使用,取其精华,适当改变,灵活使用。
个人代码没有else系列 更多文章 点击此处查看