Swift中設(shè)計(jì)模式的實(shí)踐一:責(zé)任鏈模式

本文是對(duì)Design Patterns implemented in Swift 3.0的解讀和翻譯熊镣,通過這些案例對(duì)Swift中的設(shè)計(jì)模式進(jìn)行總結(jié)和加深理解钉嘹。
本文示例代碼都是在Xcode的Playground上運(yùn)行的。

什么是設(shè)計(jì)模式

設(shè)計(jì)模式(Design Patterns)是面向?qū)ο蟪绦蜷_發(fā)過程中總結(jié)出來的代碼設(shè)計(jì)方式偶器。設(shè)計(jì)模式為程序開發(fā)所遇到的各種情景提供了最佳解決方案抬虽,合理地運(yùn)用設(shè)計(jì)模式抹沪,可以提高代碼的復(fù)用性,降低代碼的耦合度吻氧,提升程序的靈活度等等溺忧,從而有效的提高開發(fā)效率。

設(shè)計(jì)模式按功能大概可分為三類:

設(shè)計(jì)模式的淺析和實(shí)踐

行為型模式

責(zé)任鏈模式(Chain Of Responsibility)

責(zé)任鏈模式用于處理不同的請(qǐng)求(request),每個(gè)請(qǐng)求會(huì)被不同的程序處理桶蛔。
原理:為請(qǐng)求提供統(tǒng)一的方法匙头,請(qǐng)求的接收者則根據(jù)不同的請(qǐng)求進(jìn)行不同處理。多個(gè)可以接收請(qǐng)求的對(duì)象組成一條鏈仔雷,符合條件的接收者會(huì)對(duì)請(qǐng)求處理蹂析,不符合條件的接收者將請(qǐng)求傳遞給鏈的下一個(gè)接收者,直到鏈的最后碟婆。
目的:將請(qǐng)求者與接收者解耦电抚,降低代碼耦合度

示例說明:

ATM機(jī)中存在面額為100、50脑融、20喻频、10元的鈔票若干,當(dāng)向ATM查詢是否可以提取任意金額現(xiàn)金時(shí)肘迎,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))"
    }
}

調(diào)用及結(jié)果:

// 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

示例分析:

  1. 將所有同一面額的錢抽象為一個(gè)對(duì)象疤苹,同時(shí)作為責(zé)任鏈上的接收者补憾,value為面額值,quantity為該面額的數(shù)量堆生,nextPile是其鏈接的下一個(gè)接收者匣沼。
  2. canWithdraw作為請(qǐng)求的統(tǒng)一接口狰挡,canTakeSomeBill判斷當(dāng)前接收者是否可以處理請(qǐng)求,即是否需要取當(dāng)前面額的錢。(Int類型相除加叁,除數(shù)大于被除數(shù)時(shí)結(jié)果為0)倦沧。需要取錢時(shí),通過循環(huán)在當(dāng)前接收者進(jìn)行取錢它匕,當(dāng)前接收者處理之后展融,如果仍有待取金額,則傳遞給下一個(gè)接收者處理豫柬。
  3. ATM機(jī)類將面額由大到小的順序創(chuàng)建了接收鏈告希,canWithdraw作為請(qǐng)求接口,實(shí)際則是調(diào)用接收者的canWithdraw方法進(jìn)行具體的請(qǐng)求處理烧给。

小結(jié):如果不使用責(zé)任鏈模式燕偶,當(dāng)傳入一個(gè)取款請(qǐng)求時(shí),完全使用if...else...或者switch執(zhí)行础嫡,整個(gè)代碼將耦合起來指么,并且根據(jù)不同面額進(jìn)行相同的操作會(huì)導(dǎo)致代碼大量冗余和重復(fù),面額變動(dòng)時(shí)驰吓,對(duì)代碼的維護(hù)工作也將變得繁重涧尿。而使用責(zé)任鏈模式,請(qǐng)求對(duì)象只需要根據(jù)需要添加責(zé)任鏈上的接收者檬贰,而接收者處理請(qǐng)求的邏輯則不需要關(guān)心姑廉。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市翁涤,隨后出現(xiàn)的幾起案子桥言,更是在濱河造成了極大的恐慌,老刑警劉巖葵礼,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件号阿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鸳粉,警方通過查閱死者的電腦和手機(jī)扔涧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來届谈,“玉大人枯夜,你說我怎么就攤上這事〖枭剑” “怎么了湖雹?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)曙搬。 經(jīng)常有香客問我摔吏,道長(zhǎng)鸽嫂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任征讲,我火速辦了婚禮据某,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘稳诚。我一直安慰自己哗脖,他們只是感情好瀑踢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布扳还。 她就那樣靜靜地躺著,像睡著了一般橱夭。 火紅的嫁衣襯著肌膚如雪氨距。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天棘劣,我揣著相機(jī)與錄音俏让,去河邊找鬼。 笑死茬暇,一個(gè)胖子當(dāng)著我的面吹牛首昔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播糙俗,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼勒奇,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了巧骚?” 一聲冷哼從身側(cè)響起赊颠,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎劈彪,沒想到半個(gè)月后竣蹦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沧奴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年痘括,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片滔吠。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡纲菌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出屠凶,到底是詐尸還是另有隱情驰后,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布矗愧,位于F島的核電站灶芝,受9級(jí)特大地震影響郑原,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜夜涕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一犯犁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧女器,春花似錦酸役、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至丧诺,卻和暖如春入桂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背驳阎。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工抗愁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人呵晚。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓蜘腌,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親饵隙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子撮珠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容