设计模式首页投稿(暂停使用,暂停投稿)程序员

设计模式 ——— 中介者模式

2017-09-26  本文已影响0人  tomas家的小拨浪鼓

意图

用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

中介者模式的本质:封装交互。

适用性

结构

中介者模式结构图

场景解说

下面我们通过一个场景来让大家更容易对中介者模式有一个直观的认识。
场景:
感谢未来屋公司的这群好家伙,Bob拥有一个Java版本的自动屋,这可以让他的生活变得更便利。当Bob点击了打盹按钮,他的闹钟就会告诉咖啡壶开始煮咖啡。尽管生活对他来说是如此惬意,但他(以及其他的客户)总是不断地提出许多新的要求:周末不要供应咖啡......在洗澡前将喷头关闭15分钟......在丢垃圾的日子里将闹钟时刻提前......



问题:想要持续地追踪每个对象的每个规则,以及众多对象之间彼此错综复杂的关系,实在不容易。
解决方案:使用中介者模式
仔细分析上面的问题,根本原因就在于多个对象需要相互交互,从而导致对象之间紧密耦合,这就不利于对象的修改和维护。
在这个系统中加入一个中介者,一切都变得简单了。

在没有中介者的情况下,所有的对象都需要认识其他对象......也就是说,对象之间是紧耦合的。有了中介者之后,对象之间彻底解耦。
中介者内包含了整个系统的控制逻辑。当某装置需要一个新的规则时,或者是一个新的装置被加入系统内,其所有需要用到的逻辑也都被加进了中介者内。



对中介者模式实现的深入探讨

优缺点

优点

① 松散耦合
中介者模式通过把多个同事对象之间的交互封装到中介者对象里面,从而使得同事对象之间松散耦合,基本上可以做到互不依赖。这样一来,同事对象就可以独立的变化和复用,而不再像以前那样“牵一发而动全身”了。

② 集中控制交互
多个同事对象的交互,被封装在中介者对象里面集中管理,使得这些交互行为发生变化的时候,只需要修改中介者对象就可以了,而各个同事类不需要做修改。这使得你将注意力从对象各自本身的行为转移到它们之间的交互上来,这有助于弄清楚一个系统中的对象是如何交互的。

③ 多对多变成一对多
没有使用中介者模式的时候,同事对象之间的关系通常是多对多的,引入中介者对象过后,中介者对象和同事对象的关系通常变成了双向的一对多,这会让对象的关系更容易理解和实现。

缺点

① 过度集中化
中介者模式的一个潜在缺点是,如果同事对象的交互非常多,而且比较复杂,当这些复杂性全部集中到中介者的时候,会导致中介者对象变得十分的复杂,而且难于管理和维护。

广义中介者

仔细查看中介者的结构、定义和示例,会发现几个问题,使得中介者模式在实际使用的时候,变得繁琐或困难。
Q:是否有必要为同事对象定义一个公共的父类?
大家都知道,Java是单继承的,为了使用中介者模式,就让这些同事对象继承一个父类,这是很不好的;再说了,这个父类目前也没有什么特别的公共功能,也就是说继承它也得不到多少好处。
A:在实际开发中,很多相互交互的对象本身是没有公共父类的,强行加上一个父类,会让这些对象实现起来特别别扭。

Q:同事类有必要持有中介者对象吗?
同事类需要知道中介者对象,以便当它们发生改变的时候,能够通知中介者对象,但是,是否需要作为属性,并通过构造方法传入,这么强的依赖关系呢?
A:也可以有简单的方式去通知中介对象,比如把中介对象做成单例,直接在同事类的方法里面去调用中介者对象。

Q:是否需要中介者接口?
A:在实际开发中,很常见的情况是不需要中介者接口的,而且中介者对象也不需要创建很多个实例,因为中介者是用来封装和处理同事对象的关系的,它一般是没有状态需要维护的,因此中介者通常可以实现成单例。

Q:其四:中介者对象是否需要持有所有的同事?
A:虽说中介者对象需要知道所有的同事类,这样中介者才能与它们交互。但是是否需要做为属性这么强烈的依赖关系,而且中介者对象在不同的关系维护上,可能会需要不同的同事对象的实例,因此可以在中介者处理的方法里面去创建、或者获取、或者从参数传入需要的同事对象。

Q:中介者对象只是提供一个公共的方法,来接受同事对象的通知吗?
A:在实际开发中,通常会提供具体的业务通知方法,这样就不用再去判断到底是什么对象,具体是什么业务了。

实际开发中我们使用更多的是中介者模式的变种:
只要是实现封装对象之间的交互功能,就可以应用上中介者模式,而不必过于拘泥于中介者模式本身的结构。标准的中介者模式限制很多,导致能完全按照标准使用中介者模式的地方并不是很多,而且多集中在界面实现上。只要本质不变,稍稍变形一下,简化一下,或许能更好的使用中介者模式。

相关模式

中介者模式和外观模式

这两个模式有相似的地方,也存在很大的不同。

外观模式多用来封装一个子系统内部的多个模块,目的是向子系统外部提供简单易用的接口,也就是说外观模式封装的是子系统外部和子系统内部模块间的交互;而中介者模式是提供多个平等的同事对象之间交互关系的封装,一般是用在内部实现上。

另外,外观模式是实现单向的交互,是从子系统外部来调用子系统内部,不会反着来,而中介者模式实现的是内部多个模块间多向的交互。

中介者模式和观察者模式

这两个模式可以组合使用。
中介者模式可以组合使用观察者模式,来实现当同事对象发生改变的时候,通知中介对象,让中介对象去进行与其它相关对象的交互。

参考

《Head First 设计模式》
《设计模式:可复用面向对象软件的基础》
《研磨设计模式》

上一篇下一篇

猜你喜欢

热点阅读