本文是對Design Patterns implemented in Swift 3.0的解讀和翻譯,通過這些案例對Swift中的設計模式進行總結和加深理解。
本文示例代碼都是在Xcode的Playground
上運行的。
什么是設計模式
設計模式(Design Patterns)是面向對象程序開發(fā)過程中總結出來的代碼設計方式。設計模式為程序開發(fā)所遇到的各種情景提供了最佳解決方案,合理地運用設計模式,可以提高代碼的復用性,降低代碼的耦合度,提升程序的靈活度等等,從而有效的提高開發(fā)效率。
設計模式按功能大概可分為三類:
- 行為型模式(Behavioral):主要關注對象之間的通信
- 創(chuàng)建型模式(Creational):主要關注對象的創(chuàng)建,根據(jù)實際情景,通過其方法創(chuàng)建對象,而非直接實例化對象,使創(chuàng)建對象更加靈活。
- 結構型模式(Structural):關注類和對象的組合。通過繼承、協(xié)議等方式增加對象的功能。
設計模式的淺析和實踐
行為型模式
責任鏈模式(Chain Of Responsibility)
責任鏈模式用于處理不同的請求(request),每個請求會被不同的程序處理。
原理:為請求提供統(tǒng)一的方法,請求的接收者則根據(jù)不同的請求進行不同處理。多個可以接收請求的對象組成一條鏈,符合條件的接收者會對請求處理,不符合條件的接收者將請求傳遞給鏈的下一個接收者,直到鏈的最后。
目的:將請求者與接收者解耦,降低代碼耦合度
示例說明:
ATM機中存在面額為100、50、20、10元的鈔票若干,當向ATM查詢是否可以提取任意金額現(xiàn)金時,ATM返回true或false。
示例:
import Swift
import Foundation
final class MoneyPile {
let value: Int
var quantity: Int
var nextPile: MoneyPile?
init(value: Int, quantity: Int, nextPile: MoneyPile?) {
self.value = value
self.quantity = quantity
self.nextPile = nextPile
}
func canWithdraw(amount: Int) -> Bool {
var amount = amount
func canTakeSomeBill(want: Int) -> Bool {
return (want / self.value) > 0
}
var quantity = self.quantity
while canTakeSomeBill(want: amount) {
if quantity == 0 {
break
}
amount -= self.value
quantity -= 1
}
guard amount > 0 else {
return true
}
if let next = self.nextPile {
return next.canWithdraw(amount: amount)
}
return false
}
}
final class ATM {
private var hundred: MoneyPile
private var fifty: MoneyPile
private var twenty: MoneyPile
private var ten: MoneyPile
private var startPile: MoneyPile {
return self.hundred
}
init(hundred: MoneyPile,
fifty: MoneyPile,
twenty: MoneyPile,
ten: MoneyPile) {
self.hundred = hundred
self.fifty = fifty
self.twenty = twenty
self.ten = ten
}
func canWithdraw(amount: Int) -> String {
return "Can withdraw: \(self.startPile.canWithdraw(amount: amount))"
}
}
調用及結果:
// Create piles of money and link them together 10 < 20 < 50 < 100.**
let ten = MoneyPile(value: 10, quantity: 6, nextPile: nil)
let twenty = MoneyPile(value: 20, quantity: 2, nextPile: ten)
let fifty = MoneyPile(value: 50, quantity: 2, nextPile: twenty)
let hundred = MoneyPile(value: 100, quantity: 1, nextPile: fifty)
// Build ATM.
var atm = ATM(hundred: hundred, fifty: fifty, twenty: twenty, ten: ten)
atm.canWithdraw(amount: 310) // Cannot because ATM has only 300
atm.canWithdraw(amount: 100) // Can withdraw - 1x100
atm.canWithdraw(amount: 165) // Cannot withdraw because ATM doesn't has bill with value of 5
atm.canWithdraw(amount: 30) // Can withdraw - 1x20, 2x10
示例分析:
- 將所有同一面額的錢抽象為一個對象,同時作為責任鏈上的接收者,
value
為面額值,quantity
為該面額的數(shù)量,nextPile
是其鏈接的下一個接收者。 -
canWithdraw
作為請求的統(tǒng)一接口,canTakeSomeBill
判斷當前接收者是否可以處理請求,即是否需要取當前面額的錢。(Int
類型相除,除數(shù)大于被除數(shù)時結果為0)。需要取錢時,通過循環(huán)在當前接收者進行取錢,當前接收者處理之后,如果仍有待取金額,則傳遞給下一個接收者處理。 - ATM機類將面額由大到小的順序創(chuàng)建了接收鏈,
canWithdraw
作為請求接口,實際則是調用接收者的canWithdraw
方法進行具體的請求處理。
小結:如果不使用責任鏈模式,當傳入一個取款請求時,完全使用if...else...
或者switch
執(zhí)行,整個代碼將耦合起來,并且根據(jù)不同面額進行相同的操作會導致代碼大量冗余和重復,面額變動時,對代碼的維護工作也將變得繁重。而使用責任鏈模式,請求對象只需要根據(jù)需要添加責任鏈上的接收者,而接收者處理請求的邏輯則不需要關心。