美文网首页
【设计模式】15 - 多播委托模式 (Multicast Del

【设计模式】15 - 多播委托模式 (Multicast Del

作者: Lebron_James | 来源:发表于2019-05-06 19:26 被阅读0次

这篇文章是我阅读raywenderlich.comDesign Patterns by Tutorials的总结,文中的代码是我阅读书本之后根据自己的想法修改的。如果想看原版书籍,请点击链接购买。


多播委托模式属于行为模式,属于代理模式的变种。我们可以通过这种模式来创建一对多的代理模式。

这个模式涉及四个部分:

  • 需要代理的对象:这个对象可以有一个或者多个delegates
  • 代理协议:规定代理需要实现的方法
  • 代理:实现代理协议的对象
  • 多播委托:持有多个代理,并对代理进行管理

多播委托模式和代理模式的主要区别在于:多播委托模式多了一个多播委托对象。

什么时候使用

使用这个模式来创建一对多的代理模式。

简单demo

在这个demo中,我们实现这个例子:特朗普大厦发生火灾,大厦的安保中心及时通知消防中心和医院的急救中心。

从这个例子可以分析得出:1)需要代理的对象是大厦的安保中心SecurityCenter;2)代理是消防中心FireStation和医院的急救中心HospitalEmergencyCenter;3)Swift默认没有提供多播委托给我们,需要自己创建MulticastDelegate;4)代理协议FireEmergencyResponding

MulticastDelegate

final class MulticastDelegate<ProtocolType> {

    // MARK: - Helper Types

    private final class DelegateWrapper {
        weak var delegate: AnyObject?
        init(delegate: AnyObject) { self.delegate = delegate }
    }

    // MARK: - Properties

    private var delegateWrappers: [DelegateWrapper]
    private var delegates: [ProtocolType] {
        delegateWrappers = delegateWrappers.filter { $0.delegate != nil }
        return delegateWrappers.map { $0.delegate } as! [ProtocolType]
    }

    // MARK: - Initializers

    init(delegates: [ProtocolType] = []) {
        delegateWrappers = delegates
            .map { DelegateWrapper(delegate: $0 as AnyObject)}
    }

    // MARK: - Delegate Management

    func addDelegate(_ delegate: ProtocolType) {
        let wrapper = DelegateWrapper(delegate: delegate as AnyObject)
        delegateWrappers.append(wrapper)
    }

    func removeDelegate(_ delegate: ProtocolType) {
        guard let index = delegateWrappers
            .index(where: { $0.delegate === (delegate as AnyObject)}) else {
                return
        }
        delegateWrappers.remove(at: index)
    }

    func notifyDelegates(_ closure: (ProtocolType) -> Void) {
        delegates.forEach { closure($0) }
    }
}

为了保证MulticastDelegate的通用性,把它定义为泛型。

另外,为了不让MulticastDelegate强引用代理,定义了一个内部类DelegateWrapper来把代理包装起来,内部类里面弱引用代理。在内部类里面,delegate被定义为AnyObject?,而不是ProtocolType?,因为weak只能用于Class类型。

还添加了管理代理的方法。

代理协议

protocol FireEmergencyResponding: class {
    func notifyFire(at location: String)
}

火灾紧急响应,只有一个方法,通知在某个地方发生了火灾。

代理

final class FireStation: FireEmergencyResponding {
    func notifyFire(at location: String) {
        print("已经通知消防员在\(location)发生了火灾")
    }
}

final class HospitalEmergencyCenter: FireEmergencyResponding {
    func notifyFire(at location: String) {
        print("已经通知医护人员在\(location)发生了火灾")
    }
}

消防中心和医院的急救中心。

需要代理的对象

final class SecurityCenter {
    static let shared = SecurityCenter()
    let multicastDelegate = MulticastDelegate<FireEmergencyResponding>()
}

大厦的安保中心,因为安保中心通常只有一个,所以这里使用了单例。

使用

let securityCenter = SecurityCenter.shared
var fireStation: FireStation! = FireStation()
let hospital = HospitalEmergencyCenter()

securityCenter.multicastDelegate.addDelegate(fireStation)
securityCenter.multicastDelegate.addDelegate(hospital)

securityCenter.multicastDelegate.notifyDelegates {
    $0.notifyFire(at: "特朗普大厦")
}

print("======分割线======")

fireStation = nil

securityCenter.multicastDelegate.notifyDelegates {
    $0.notifyFire(at: "特朗普大厦")
}

// 结果
已经通知消防员在特朗普大厦发生了火灾
已经通知医护人员在特朗普大厦发生了火灾
======分割线======
已经通知医护人员在特朗普大厦发生了火灾

首先创建了两个代理:fireStationhospital。把fireStation定义为FireStation!,这样后面我们可以把fireStation设置为nil。然后把两个代理添加到multicastDelegate,接着通知特朗普大厦发生火灾,得到了我们预期的打印结果。

fireStation设置为nil之后,只有医院接收到了通知。

总结

多播委托模式非常适合用于把信息告诉代理的场景。如果是需要多个代理提供数据,这种模式就不适合了。

欢迎加入我管理的Swift开发群:536353151

下一篇文章:【设计模式】16 - 门面模式 (Facade Pattern)

相关文章

  • 【设计模式】15 - 多播委托模式 (Multicast Del

    这篇文章是我阅读raywenderlich.com的Design Patterns by Tutorials的总结...

  • 网卡模式

    广播(Broadcast)模式多播(Multicast)模式单播模式(Unicast)混杂模式(Promiscuo...

  • Multicast Delegates 多播委托

    意义解释:一个委托包含多个方法 A delegate that wraps more than one metho...

  • 一文彻底搞懂Kotlin中的委托

    1. 什么是委托? 委托,也就是委托模式,它是23种经典设计模式种的一种,又名代理模式,在委托模式中,有2个对象参...

  • 设计模式-委派模式

    设计模式-委派模式 定义 委派模式(Delegate Pattern)又叫委托模式,是一种面向对象的设计模式,允许...

  • 用委托者模式实现的多类型Adapter

    场景 面对多类型的列表,应该怎么处理? 解决方案(设计思想的方法--委托者模式) 什么是委托者模式,简单的来说就是...

  • 项目管理委托的模式和设计任务委托的模式

    知识点:【了解】项目管理委托的模式和设计任务委托的模式【掌握】项目总承包的模式 一、项目管理委托的模式★ 国际上业...

  • 浅谈iOS设计模式

    序言:设计模式是一种编码经验,设计模式有MVC模式,工厂模式,单例模式,委托模式,MVVM模式,观察者模式。iOS...

  • 委托模式

    一、委托模式简介 (注:)不属于 23 种设计模式之一,是面向对象设计模式中常用的一种模式。 特点:持有被委托人的...

  • Kotlin委托

    Kotlin委托 1.Kotlin中的委托有两种形式,一种是委托模式,一种是委托属性。 2.委托模式是设计模式中的...

网友评论

      本文标题:【设计模式】15 - 多播委托模式 (Multicast Del

      本文链接:https://www.haomeiwen.com/subject/zradoqtx.html