最近在学习设计模式,把学习过程中的点滴思考记录下来,其中也有一些从网上看到的精彩解析。
先从中介者模式开始记录。
精髓:将一堆对象(同事类)之间的复杂交互,封装到中介类中,统一协调处理。
这个图挺经典的:是这个模式,类间的处理过程。
-----------------------------------------------------------------------------------
以下是别人的理解,copy之。
1:中介者模式的功能
中介者的功能非常简单,就是封装对象之间的交互。如果一个对象的操作会引起其它相关对象的变化,或者是某个操作需要引起其它对象的后续或连带操作,而这个对象又不希望自己来处理这些关系,那么就可以找中介者,把所有的麻烦扔给它,只在需要的时候通知中介者,其它的就让中介者去处理就可以了。
反过来,其它的对象在操作的时候,可能会引起这个对象的变化,也可以这么做。最后对象之间就完全分离了,谁都不直接跟其它对象交互,那么相互的关系,全部被集中到中介者对象里面了,所有的对象就只是跟中介者对象进行通信,相互之间不再有联系。
把所有对象之间的交互都封装在中介者当中,无形中还得到另外一个好处,就是能够集中的控制这些对象的交互关系,这样有什么变化的时候,修改起来就很方便。
2:需要Mediator接口吗
有没有使用Mediator接口的必要,取决于是否会提供多个不同的中介者实现。如果中介者实现只有一个的话,而且预计中也没有需要扩展的要求,那么就可以不定义Mediator接口,让各个同事对象直接使用中介者实现对象;如果中介者实现不只一个,或者预计中有扩展的要求,那么就需要定义Mediator接口,让各个同事对象来面向中介者接口编程,而无需关心具体的中介者实现。
3:同事关系
在中介者模式中,要求这些类都要继承相同的类,也就是说,这些对象从某个角度讲是同一个类型,算是兄弟对象。
正是这些兄弟对象之间的交互关系很复杂,才产生了把这些交互关系分离出去,单独做成中介者对象,这样一来,这些兄弟对象就成了中介者对象眼里的同事。
4:同事和中介者的关系
中介者对象和同事对象之间是相互依赖的 。
5:如何实现同事和中介者的通信
一种实现方式是在Mediator接口中定义一个特殊的通知接口,作为一个通用的方法,让各个同事类来调用这个方法 。
另外一种实现方式是可以采用观察者模式,把Mediator实现成为观察者,而各个同事类实现成为Subject,这样同事类发生了改变,会通知Mediator。Mediator在接到通知过后,会与相应的同事对象进行交互。 (这个看了半天,貌似没有什么区别,望明白人指点一二)
应用:
广义中介者示例——部门与人员
1:部门和人员的关系 : 是 多对多的
2:问题的出现
想想部门和人员的功能交互,举几个常见的功能:
(1)部门被撤销
(2)部门之间进行合并
(3)人员离职
(4)人员从一个部门调职到另外一个部门
想想要实现这些功能,按照前面的设计,该怎么做呢?
(1)系统运行期间,部门被撤销了,就意味着这个部门不存在了,可是原来这个部门下所有的人员,每个人员的所属部门中都有这个部门呢,那么就需要先通知所有的人员,把这个部门从它们的所属部门中去掉,然后才可以清除这个部门。
(2)部门合并,是合并成一个新的部门呢,还是把一个部门并入到另一个部门?如果是合并成一个新的部门,那么需要把原有的两个部门撤销,然后再新增一个部门;如果是把一个部门合并到另一个部门里面,那就是撤销掉一个部门,然后把这个部门下的人员移动到这个部门。不管是那种情况,都面临着需要通知相应的人员进行更改这样的问题。
(3)人员离职了,反过来就需要通知他所属于的部门,从部门的拥有人员的记录中去除掉这个人员。
(4)人员调职,同样需要通知相关的部门,先从原来的部门中去除掉,然后再到新的部门中添加上。
看了上述的描述,感觉如何?
麻烦的根源在什么地方呢?仔细想想,对了,麻烦的根源就在于部门和人员之间的耦合,这样导致操作人员的时候,需要操作所有相关的部门,而操作部门的时候又需要操作所有相关的人员,使得部门和人员搅和在了一起。
3:中介者来解决
找到了根源就好办了,采用中介者模式,引入一个中介者对象来管理部门和人员之间的关系,就能解决这些问题了。
如果采用标准的中介者模式,想想上面提出的那些问题点吧,就知道实现起来会很别扭。因此采用广义的中介者来解决,这样部门和人员就完全解耦了,也就是说部门不知道人员,人员也不知道部门,它们完全分开,它们之间的关系就完全由中介者对象来管理了。
中介者模式的优缺点
1:松散耦合
2:集中控制交互
3:多对多变成一对多
4:过度集中化
思考中介者模式
中介者模式的本质
中介者模式的本质是: 封装交互
何时选用中介者模式
1:如果一组对象之间的通信方式比较复杂,导致相互依赖、结构混乱,可以采用中介者模式,把这些对象相互的交互管理起来,各个对象都只需要和中介者交互,从而使得各个对象松散耦合,结构也更清晰易懂
2:如果一个对象引用很多的对象,并直接跟这些对象交互,导致难以复用该对象。可以采用中介者模式,把这个对象跟其它对象的交互封装到中介者对象里面,这个对象就只需要和中介者对象交互就可以了
原文地址:【抱歉,网址中的单词是违禁内容】
这位大侠,这个例子举的好,是很经典的应用,以前在做项目时,一直没处理好复杂对象间的依赖问题,这次有了这个,再有类似需求,相信迎刃而解。
上图,中介者实现类是依赖同事实现类的,通过SET()注入。不适用构造函数注入的原因是中介者中并不一定包含某一个同事类,这应该由Client来决定。
而同事抽象类是依赖于中介者抽象类的,通过构造函数注入。
在学习时,一度对中介者和命令模式产生混淆,因为他们的实现方式,有些类似。仔细分析下还是有很大差别的。
1、程序结构的差异:虽然都是通过增加个中间件来聚合起来原来的业务类,但是中介者模式的这个中间件(中介类)对用户来说是完全透明的,不提供对外接口。用户只需要实例化一下,再指定给业务类。用户调取的依然是原来的业务类(同事类),同事类中,有一部分方法能自己实现,其他不能实现的方法,才会去通过实例化时指定的中介者对象自动调取中介者里面的相应方法,协调实现。
而命令模式则不然,命令模式,会把业务类完全对用户屏蔽,继承一个又一个的子类来实现一个又一个的具体命令,然后把这个命令类暴露给用户,用户关注的也仅仅是这个Command命令类。
2、性质:中介者模式里的业务类(同事类)之间,是有强烈的耦合关系的。
命令模式里面的业务类,可以没什么相关性。
二者的相同点就是,在抽象中介者和抽象命令类里,都需要定义具体的业务对象。