設計模式一書中引用了商場促銷的例子來講解策略模式.現在我們就來看看代碼
1.0版本
class ViewController: UIViewController {
var total:Double = 0.0 // 總計
var price:Double = 50 // 單價
var num:Double = 3 // 數量
override func viewDidLoad() {
super.viewDidLoad()
let totalPrices = price * num
total = total + totalPrices
print("總價為:", total)
// 總價為:150
}
}
加入打折操作
class ViewController: UIViewController {
var total:Double = 0.0 // 總計
var price:Double = 50 // 單價
var num:Double = 3 // 數量
var payMod = "正常收費" // 收費模式
override func viewDidLoad() {
super.viewDidLoad()
var totalPrices:Double = 0
switch payMod {
case "正常收費":
totalPrices = price * num
case "8折":
totalPrices = price * num * 0.8
case "75折":
totalPrices = price * num * 0.75
case "5折":
totalPrices = price * num * 0.5
default:
break
}
total = total + totalPrices
print("單價:",price,"個數:",num, "收費模式:",payMod,"合計:", total)
// 單價:50 個數:3 收費模式:正常收費 總價為:150
}
}
再來看看使用簡單工廠模式的寫法
class CashSuper: NSObject {
//現金父類
func acceptCash(money:Double)->Double{
return money
}
}
class CashNormal: CashSuper {
// 正常收費子類
override func acceptCash(money: Double) -> Double {
return money
}
}
class CashRebate: CashSuper {
// 打折收費子類
private var moneyRebate:Double = 1.0
// 初始化方法
init(moneyRebate:Double) {
self.moneyRebate = moneyRebate
}
override func acceptCash(money: Double) -> Double {
return money * moneyRebate
}
}
class CashReturn: CashSuper {
// 返利收費子類
private var moneyCondition:Double = 0.0
private var moneyReturn:Double = 0.0
// 初始化方法
init(moneyCondition:Double, moneyReturn:Double) {
self.moneyCondition = moneyCondition
self.moneyReturn = moneyReturn
}
override func acceptCash(money: Double) -> Double {
var result = money
if money >= moneyCondition {
result = money - floor(money / moneyCondition) * moneyReturn
}
return result
}
class CashFactory {
//工廠類
static func createCashAccept(type:String)->CashSuper {
var cs: CashSuper?
switch type {
case "正常收費":
cs = CashNormal()
case "滿300返100":
cs = CashReturn(moneyCondition: 300, moneyReturn: 100)
case "打8折":
cs = CashRebate(moneyRebate: 0.8)
default:
break
}
return cs!
}
}
class ViewController: UIViewController {
// 客戶端代碼
var total:Double = 0.0 // 總計
var price:Double = 50 // 單價
var num:Double = 3 // 數量
var payMod = "正常收費"
override func viewDidLoad() {
super.viewDidLoad()
let csuper = CashFactory.createCashAccept(payMod)
var totalPrices:Double = 0
// 傳入商品總價
totalPrices = csuper.acceptCash(price * num)
total = total + totalPrices
print("單價:",price,"個數:",num, "收費模式:",payMod,"合計:", total)
// 單價:50 個數:3 收費模式:正常收費 總價為:150
}
}
如果我們使用策略模式寫的話會是什么樣子?
策略模式只需要在增加一個context類
class CashContext: NSObject {
private var cs:CashSuper
init(csuper:CashSuper) {
self.cs = csuper
}
func getResult(money:Double)->Double{
return cs.acceptCash(money)
}
}
客戶端代碼
class ViewController: UIViewController {
var total:Double = 0.0 // 總計
var price:Double = 50 // 單價
var num:Double = 3 // 數量
var payMod = "正常收費"
override func viewDidLoad() {
super.viewDidLoad()
var cc: CashContext?
switch payMod {
case "正常收費":
cc = CashContext(csuper: CashNormal())
case "滿300返100":
cc = CashContext(csuper: CashReturn(moneyCondition: 300, moneyReturn: 100))
case "打8折":
cc = CashContext(csuper: CashRebate(moneyRebate: 0.8))
default:
break
}
var totalPrices:Double = 0
totalPrices = cc!.getResult(price * num)
total = total + totalPrices
print("單價:",price,"個數:",num, "收費模式:",payMod,"合計:", total)
// 單價:50 個數:3 收費模式:正常收費 總價為:150
}
}
使用策略模式的話,進行判斷的語句又回到了客戶端代碼中,這肯定不是我們想要的結果那么將策略模式和簡單工廠模式結合一下
再來看看策略模式和簡單工廠模式的結合版
需要修改cashContext類
class CashContext: NSObject {
private var cs:CashSuper?
init(type:String) {
switch type {
case "正常收費":
cs = CashNormal()
case "滿300返100":
cs = CashReturn(moneyCondition: 300, moneyReturn: 100)
case "打8折":
cs = CashRebate(moneyRebate: 0.8)
default:
break
}
}
func getResult(money:Double)->Double{
return cs!.acceptCash(money)
}
}
客戶端代碼修改
class ViewController: UIViewController {
var total:Double = 0.0 // 總計
var price:Double = 50 // 單價
var num:Double = 3 // 數量
var payMod = "正常收費"
override func viewDidLoad() {
super.viewDidLoad()
var csuper: CashContext?
csuper = CashContext(type: payMod)
var totalPrices:Double = 0
totalPrices = csuper!.getResult(price * num)
total = total + totalPrices
print("單價:",price,"個數:",num, "收費模式:",payMod,"合計:", total)
// 單價:50 個數:3 收費模式:正常收費 總價為:150
}
}
策略模式就是封裝算法的,但在實踐中,我們發現可以用它來封裝幾乎任何類型的規則, 只要在分析過程中聽到需要在不同時間應用不同的業務規則,就可以考慮使用策略模式處理這種變化的可能性
但是在基本的策略模式中, 選擇所用的具體實現職責還是由客戶端對象在承擔,并轉給策略模式的Context對象.這本身并沒有接觸客戶端需要選擇判斷的壓力,而策略模式與簡單工廠模式節后和,選擇具體時間的職責也可以由Context來承擔,這就最大化減輕了客戶端的職責.
但是書中還提到這不是最優的解決辦法.讓我們繼續之后的學習吧~
@旺仔牛奶
2016年3月29日