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

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

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

設(shè)計(jì)模式(Design Patterns)是面向?qū)ο蟪绦蜷_發(fā)過(guò)程中總結(jié)出來(lái)的代碼設(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)求者與接收者解耦,降低代碼耦合度

示例說(shuō)明:

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í),通過(guò)循環(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è)代碼將耦合起來(lái),并且根據(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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容