Swift中設計模式的實踐一:責任鏈模式

本文是對Design Patterns implemented in Swift 3.0的解讀和翻譯,通過這些案例對Swift中的設計模式進行總結和加深理解。
本文示例代碼都是在Xcode的Playground上運行的。

什么是設計模式

設計模式(Design Patterns)是面向對象程序開發(fā)過程中總結出來的代碼設計方式。設計模式為程序開發(fā)所遇到的各種情景提供了最佳解決方案,合理地運用設計模式,可以提高代碼的復用性,降低代碼的耦合度,提升程序的靈活度等等,從而有效的提高開發(fā)效率。

設計模式按功能大概可分為三類:

設計模式的淺析和實踐

行為型模式

責任鏈模式(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

示例分析:

  1. 將所有同一面額的錢抽象為一個對象,同時作為責任鏈上的接收者,value為面額值,quantity為該面額的數(shù)量,nextPile是其鏈接的下一個接收者。
  2. canWithdraw作為請求的統(tǒng)一接口,canTakeSomeBill判斷當前接收者是否可以處理請求,即是否需要取當前面額的錢。(Int類型相除,除數(shù)大于被除數(shù)時結果為0)。需要取錢時,通過循環(huán)在當前接收者進行取錢,當前接收者處理之后,如果仍有待取金額,則傳遞給下一個接收者處理。
  3. ATM機類將面額由大到小的順序創(chuàng)建了接收鏈,canWithdraw作為請求接口,實際則是調用接收者的canWithdraw方法進行具體的請求處理。

小結:如果不使用責任鏈模式,當傳入一個取款請求時,完全使用if...else...或者switch執(zhí)行,整個代碼將耦合起來,并且根據(jù)不同面額進行相同的操作會導致代碼大量冗余和重復,面額變動時,對代碼的維護工作也將變得繁重。而使用責任鏈模式,請求對象只需要根據(jù)需要添加責任鏈上的接收者,而接收者處理請求的邏輯則不需要關心。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容