嗯,個人代碼沒有
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系列 更多文章 點擊此處查看