iOS Developer

Swift设计模式——责任链模式

2017-05-26  本文已影响0人  晓晓魔导师

什么是责任链模式?

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

<br />

使用场景:

  1. 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
  2. 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
  3. 可动态指定一组对象处理请求。

<br />

示例:

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 //100面额的钱堆
    private var fifty: MoneyPile //50面额的钱堆
    private var twenty: MoneyPile //20面额的钱堆
    private var ten: MoneyPile //10面额的钱堆
    
    //优先寻找的钱堆
    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))"
    }
    
}

//创建如下钱堆,并将它们整理(连接)在一起。
let ten = MoneyPile(value: 10, quantity: 6, nextPile: nil) //里面有6个面额为10元的金币
let twenty = MoneyPile(value: 20, quantity: 2, nextPile: ten) //里面有2个面额为20元的金币
let fifty = MoneyPile(value: 50, quantity: 2, nextPile: twenty) //里面有2个面额为50元的金币
let hundred = MoneyPile(value: 100, quantity: 1, nextPile: fifty) //里面有1个面额为100元的金币

//创建银行
var atm = ATM(hundred: hundred, fifty: fifty, twenty: twenty, ten: ten)

//
atm.canWithdraw(amount: 300) //输出: Can withdraw: true ,因为银行里金币总价值300
atm.canWithdraw(amount: 130) //输出: Can withdraw: true,因为可以取1个100面额的金币+1个20面额的金币+1个10面额的金币组成。
atm.canWithdraw(amount: 105) //输出:Can withdraw: false, 因为没有一个钱堆有面额为5的金币。

<br />

优点

  1. 降低耦合度。它将请求的发送者和接收者解耦。
  2. 简化了对象。使得对象不需要知道链的结构。
  3. 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
  4. 增加新的请求处理类很方便。

缺点

  1. 不能保证请求一定被接收。
  2. 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
  3. 可能不容易观察运行时的特征,有碍于除错。
上一篇下一篇

猜你喜欢

热点阅读