中介者模式

基本概念

在面向对象的设计中是鼓励把行为分散到不同的对象中的,虽然把行为分散到不同的对象之间能增加复用性,但是这样的话可能会导致对象与对象相互关联的越来越多,这样的话就会使对象很难在不依赖对象的情况下独立工作,而且由于行为分布于多个对象,如果我们要去修改某个行为的话可能就很难的去修改,这样的话我们去创建的类就会越来越多,通过这样的方式去支持应用程序的新行为。


中介者模式的话其实就是让对象的交互在一个中介者中进行处理,其他的对象不需要去进行彼此的交互,这样可以松散耦合,减少了它们之间的依赖的关系,其实也就是说我让这些对象的交互都通过一个中介者来做,这样的话,我那么类对象彼此的结构都可以进行一个很好的修改

在现实生活中其实中介者模式也是在很多方面都存在的,就比如说我们经常使用的电脑如果缺乏主板,那么CPU,显卡,声卡这些都无法与外界直接进行交互,其实这就是一个中介者。


在中介者模式中有几个概念我们是需要知道的,如下所示

  • 1、抽象的中介者接口Mediator,这里面一般定义的是用于各个colleague交互的一般的行为
  • 2、具体中介者实现对象ConcreteMeditor主要就是去维护各个同事对象,负责协调各个同事对象之间的交互关系,就好比电影中的一个导演,导演应该知道所有的参与影片的角色以及场景的变换,如果电影在这拍摄期间的需求有任何的改变,导演应该是第一个知道的,然后去进行资源和人力的调整。
  • 3、抽象的同事类Colleague主要就是用于约束同事对象的类型,并且可以去实现一些同事类当中要进行交互的一些公共的功能。
  • 4、具体的同事类ConcreteColleague 首先肯定要先实现自己的业务,如果要和其他的同事进行交互的话,就去通过引用的中介者来进行交互,一般来说每一个具体的同事类的对象都会去引用中介者对象

UML结构图

中介者模式的主要应用场景

  • 1、对象之间的交互很复杂时,也就是说如果导致一组对象之间相互依赖这样耦合性会很强。
  • 2、对象引用了很多其他的对象导致对象很难进行复用
  • 3、想要做一个分布在多个类中的逻辑或者是行为,但是不想生成太多的类的。

其实MVP的架构用到的就是中介者模式的思想,我通过P层将view和viewController的业务逻辑都抽给P层,这样我在viewController当中只需要去调用P层提供的接口就好

下面就举一个CD设备设置去读取数据需要通过声卡和显卡去播放我的数据,这里我们不用让CD设备之间去引用声卡和显卡,这样形成紧耦合关系,而是我们去使用中介者模式,利用Computer作为一个中介,这里主要理解思想


抽象中介者

//抽象的中介者
//它会持有同事的引用
class ComputerMediator: NSObject {

    func changed(colleague:ComputerColleague)
    {
        
    }
}

抽象同事

import UIKit

//抽象同事
class ComputerColleague: NSObject {

    //持有中介者
    var mediator:ComputerMediator
    
    init(mediator:ComputerMediator) {
        self.mediator = mediator
    }
}

具体同事DisplayCard(显卡)

import UIKit

//显卡
class DisplayCard: ComputerColleague {
    
    override init(mediator: ComputerMediator) {
        super.init(mediator: mediator)
    }
    
    //播放视频数据
    func videoPlay(data:String) {
        print("播放视频...")
    }
    
}

具体同事SoundCard(声卡)

import UIKit

//声卡
class SoundCard: ComputerColleague {
    
    override init(mediator: ComputerMediator) {
        super.init(mediator: mediator)
    }
    
    //播放视频数据
    func soundPlay(data:String) {
        print("播放音频...")
    }
    
}

具体同事CD设备

import UIKit

//CD设备->负责读取光盘数据传递给电脑
class CDDevice: ComputerColleague {

    private var data:String?
    
    override init(mediator: ComputerMediator) {
        super.init(mediator: mediator)
    }
    
    
    func read() -> String {
        return self.data!
    }
    
    func load() {
        //数据格式就是两个数据之间隔得是逗号,所以下面CPU也是这么解析数据的
        self.data = "视频数据,音频数据"
        mediator.changed(colleague: self)
    }
    
}

具体同事CPU,里面定义了如何去解析数据就是通过decodeData方法,这个方法就是专门为了解析我CD里面固定格式的数据来生成的,这里decodeData之后,又去调用中介者的change方法就是把数据给传递给了声卡和显卡,下面在Computer中介者类当中会有介绍

import UIKit

//同事
class CPU: ComputerColleague {
    
    //视频数据
    private var videoData:String?
    //音频数据
    private var soundData:String?
    
    override init(mediator: ComputerMediator) {
        super.init(mediator: mediator)
    }
    
    func getVideoData() -> String {
        return self.videoData!
    }
    
    func getSoundData() -> String {
        return self.soundData!
    }
    
    func decodeData(data:String) {
        let array = data.split(separator: ",").map(String.init)
        self.videoData = array[0]
        self.soundData = array[1]
        mediator.changed(colleague: self)
    }
    
    
}

然后就是具体的中介者SXComputerMediator

import UIKit

//具体的中介者
class SXComputerMediator: ComputerMediator {

    private var cpu:CPU?
    private var displayCard:DisplayCard?
    private var soundCard:SoundCard?
    private var cdDevice:CDDevice?
    
    func setCPU(cpu:CPU) {
        self.cpu = cpu
    }
    
    func setDisplayCard(displayCard:DisplayCard) {
        self.displayCard = displayCard
    }
    
    func setSoundCard(soundCard:SoundCard) {
        self.soundCard = soundCard
    }
    
    func setCDDevice(cdDevice:CDDevice) {
        self.cdDevice = cdDevice
    }
    
    override func changed(colleague: ComputerColleague) {
        if colleague == cpu {
            self.handleCPU(cpu: colleague as! CPU)
        } else if colleague == cdDevice {
            self.handleCD(cd: colleague as! CDDevice)
        }
    }
    
    //CPU读取数据
    //解析数据
    private func handleCD(cd:CDDevice) {
        cpu?.decodeData(data: cd.read())
    }
    
    //设备交互
    private func handleCPU(cpu:CPU) {
        self.soundCard?.soundPlay(data: cpu.getSoundData())
        self.displayCard?.videoPlay(data: cpu.getVideoData())
    }
    
}

然后就是我们进行使用,去创建中介者对象,然后设置好其的同事之后,直接调用同事的方法

        let mediator = SXComputerMediator()
        //零件->同事
        let cpu = CPU(mediator: mediator)
        let displayCard = DisplayCard(mediator: mediator)
        let soundCard = SoundCard(mediator: mediator)
        let cdDevice = CDDevice(mediator: mediator)
        
        mediator.setCPU(cpu: cpu)
        mediator.setSoundCard(soundCard: soundCard)
        mediator.setDisplayCard(displayCard: displayCard)
        mediator.setCDDevice(cdDevice:cdDevice)
        
        cdDevice.load()

下面就是显示的结果,解析数据成功

当然如果我们使用了中介者模式的话,是以中介者内部的复杂的业务逻辑的判断去取代了交互的复杂性,因为中介者去封装了和合并了colleague的各种的协作的逻辑,所以中介者可能会变得很复杂很难进行维护。这样的话其实我们可以去使用策略模式来进行分解。当然策略模式主要是对固定的算法进行应用的,所以我们使用的时候也要注意

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值