中介者模式使修改、扩展和重用单个组件变得容易,因为它们不再依赖于所有其他类。下面我们举一个简单的例子来说明怎么在程序里使用中介者模式减少各个组件类之间的耦合。
在现实生活中,机场的控制塔是一个典型的中介者角色, 飞机在起飞和降落前都会向控制塔发出问询,控制塔会给飞机发送指令协调它们的起飞降落时间,避免造成事故。
现在假设一个机场只有一条跑道,即同一时刻只能承载一架飞机的起飞和降落,飞机和飞机之间不能直接沟通,这样就乱套了,必须由控制塔作为一个中介者向各个飞机(组件)同步跑道的可用状态。下面我们先来定义飞机和指挥塔--即组件和中介者的 Interface 接口。
(资料图)
"本文使用的完整可运行源码去公众号「网管叨bi叨」发送【设计模式】即可领取"//中介者--机场指挥塔的接口定义typemediatorinterface{canLanding(airplaneairplane)boolnotifyAboutDeparture()}//组件--飞行器的接口定义typeairplaneinterface{landing()takeOff()permitLanding()}接下来我们来实现具体的组件,这里提供两个组件作为演示,一架波音飞机和一架空客飞机。
每个飞机在降落landing方法里都会去跟作为中介者的指挥塔发出问询,看是否能够降落,如果跑道正在被占用,那么会等待指挥塔调用它自己的permitLanding()通知可以降落后再降落。而其他占用跑道的飞机在起飞后会通过中介者提供的notifyAboutDeparture()告知指挥塔自己的离去。
具体的代码如下:
"本文使用的完整可运行源码去公众号「网管叨bi叨」发送【设计模式】即可领取"//组件1--波音飞机typeboeingPlanestruct{mediator}func(b*boeingPlane)landing(){if!b.mediator.canLanding(b){fmt.Println("Airplane Boeing:飞机跑到正在被占用,无法降落!")return}fmt.Println("Airplane Boeing:已成功降落!")}func(b*boeingPlane)takeOff(){fmt.Println("Airplane Boeing:正在起飞离开跑道!")b.mediator.notifyAboutDeparture()}func(b*boeingPlane)permitLanding(){fmt.Println("Airplane Boeing:收到指挥塔信号,允许降落,正在降落!")b.landing()}//组件2--空客飞机typeairBusPlanestruct{mediatormediator}func(airbus*airBusPlane)landing(){if!airbus.mediator.canLanding(airbus){fmt.Println("Airplane AirBus:飞机跑到正在被占用,无法降落!")return}fmt.Println("Airplane AirBus:已成功降落!")}func(airbus*airBusPlane)takeOff(){fmt.Println("Airplane AirBus:正在起飞离开跑道!")airbus.mediator.notifyAboutDeparture()}func(airbus*airBusPlane)permitLanding(){fmt.Println("Airplane AirBus:收到指挥塔信号,允许降落,正在降落!")airbus.landing()}作为中介者的指挥塔,提供两个方法
"本文使用的完整可运行源码去公众号「网管叨bi叨」发送【设计模式】即可领取"//中介者实现--指挥塔typemanageTowerstruct{isRunwayFreeboolairportQueue[]airplane}func(tower*manageTower)canLanding(airplaneairplane)bool{iftower.isRunwayFree{//跑道空闲,允许降落,同时把状态变为繁忙tower.isRunwayFree=falsereturntrue}//跑道繁忙,把飞机加入等待通知的队列tower.airportQueue=append(tower.airportQueue,airplane)returnfalse}func(tower*manageTower)notifyAboutDeparture(){if!tower.isRunwayFree{tower.isRunwayFree=true}iflen(tower.airportQueue)>0{firstPlaneInWaitingQueue:=tower.airportQueue[0]tower.airportQueue=tower.airportQueue[1:]firstPlaneInWaitingQueue.permitLanding()}}funcnewManageTower()*manageTower{return&manageTower{isRunwayFree:true,}}这样我们就可以通过指挥塔,协调多个飞机使用飞机场跑道进行有序的起飞和降落了。
"本文使用的完整可运行源码去公众号「网管叨bi叨」发送【设计模式】即可领取"funcmain(){tower:=newManageTower()boeing:=&boeingPlane{mediator:tower,}airbus:=&airBusPlane{mediator:tower,}boeing.landing()airbus.landing()boeing.takeOff()}执行程序后,会有类似下面的输出:
本文的完整源码,已经同步收录到我整理的电子教程里啦,可向我的公众号「网管叨bi叨」发送关键字【设计模式】领取。
看完例子对中介者模式有了一定了解后我们接下来再详细说说它的构成以及用代码实现中介者模式的步骤。
中介者模式的构成
中介者模式的结构构成可以用下面的UML类图来表示图中的各个类的构成跟我们上面代码实例中列举的十分类似,Component 实现类里需要持有指向中介者的引用,中介者里也保有对各个组件对象的引用,只不过示例里是把组件保存在一个列表里,UML 中是把各个组件单独保存在了中介者的属性里。
下面我们再把用代码实现中介者模式的步骤简单叙述一遍:
中介模式与观察者模式区别
中介模式与观察者模式在结构上有些相似,观察者模式中的EventDispatcher 和 中介模式中的 Mediator 看起来很想,都是把多个组件之间的关系,维护到自身,实现组件间的间接通信达到解构效果,不过这两个设计模式在使用场景或者叫要解决的问题上,还是有些差别
总结
中介者模式(Mediator Pattern)又叫作调解者模式或调停者模式。用一个中介对象封装一系列对象交互, 中介者使各对象不需要显式地相互作用, 从而使其耦合松散, 而且可以独立地改变它们之间的交互, 属于行为型设计模式。
中介者模式主要适用于以下应用场景。
中介者模式的优点
中介者模式的缺点
最后
今天这篇完结后,用Go学设计模式就正式更新完了,算是一个小小的成就,大家可以在专辑链接里查看系列里的其他文章,后面会写篇总结把设计模式的学习心法给大家说一说,其实就是多看,多练,除此之外也有点小技巧,咱们放到后面给系列收尾时再说。
大家可以期待一下,没有关注的记得给个关注。
扫码关注公众号「网管叨bi叨」
给网管个星标,第一时间吸我的知识
网管整理了一本《Go 开发参考书》收集了70多条开发实践。去公众号回复【gocookbook】领取!还有一本《k8s 入门实践》讲解了常用软件在K8s上的部署过程,公众号回复【k8s】即可领取!
觉得有用就点个在看