策略模式定义了算法家族,在调用算法家族的时候不感知算法的变化,客户也不会受到影响。
下面用《大话设计模式》中的一个实例进行改写。
例:超市中经常进行促销活动,促销活动的促销方法就是一个个策略,如“满一百减20”,“打八折”等。现在实现策略模式,用CashContext生产策略,并完成策略的调用。
1.首先定义所有策略的接口。
package cash type cashSuper interface { AcceptMoney(money float64) float64 }
2.定义三个子类,实现此接口
package cash //普通情况,没有折扣 type cashNormal struct { } func newCashNormal() cashNormal { instance := new(cashNormal) return *instance } func (c cashNormal) AcceptMoney(money float64) float64 { return money }
package cash //打折,传入打折的折扣,如0.8 type cashRebate struct { Rebate float64 //折扣 } func newCashRebate(rebate float64) cashRebate { instance := new(cashRebate) instance.Rebate = rebate return *instance } func (c cashRebate) AcceptMoney(money float64) float64 { return money * c.Rebate }
package cash //直接返利,如满100返20 type cashReturn struct { MoneyCondition float64 MoneyReturn float64 } func newCashReturn(moneyCondition float64, moneyReturn float64) cashReturn { instance := new(cashReturn) instance.MoneyCondition = moneyCondition instance.MoneyReturn = moneyReturn return *instance } func (c cashReturn) AcceptMoney(money float64) float64 { if money >= c.MoneyCondition { moneyMinus := int(money / c.MoneyCondition) return money - float64(moneyMinus)*c.MoneyReturn } return money }
3.最重要的时刻来临了,定义CashContext结构,用来做策略筛选
package cash type CashContext struct { Strategy cashSuper } func NewCashContext(cashType string) CashContext { c := new(CashContext) //这里事实上是简易工厂模式的变形,用来生产策略 switch cashType { case "打八折": c.Strategy = newCashRebate(0.8) case "满一百返20": c.Strategy = newCashReturn(100.0, 20.0) default: c.Strategy = newCashNormal() } return *c } //在策略生产成功后,我们就可以直接调用策略的函数。 func (c CashContext) GetMoney(money float64) float64 { return c.Strategy.AcceptMoney(money) }
4.调用测试
package main import ( "cash" "fmt" ) func main() { money := 100.0 cc := cash.NewCashContext("打八折") money = cc.GetMoney(money) fmt.Println("100打八折实际金额为", money) money = 199 cc = cash.NewCashContext("满一百返20") money = cc.GetMoney(money) fmt.Println("199满一百返20实际金额为", money) money = 199 cc = cash.NewCashContext("没有折扣") money = cc.GetMoney(money) fmt.Println("199没有折扣实际金额为", money) } /*************************************** 输出: 100打八折实际金额为 80 199满一百返20实际金额为 179 199没有折扣实际金额为 199 */
总结:策略模式解除了客户对策略的感知,所有策略,甚至cashSuper皆为私有。只需要暴露CashContext就可以生成策略。降低了耦合。