什么是Mediator模式?
中介者模式的定义为
- Define an object that encapsulates how a set of objects interact. (用一个中介对象封装一系列对象的交互。)
- Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.(中介者使得个对象不需要显式的相互作用,从而使其松散耦合,而且独立地改变他们之间的交互。)
Mediator模式是较为广泛使用的一种模式,它的优点就是把原有的1对多的依赖变成1对1的依赖,减少了依赖,降低了耦合,比如在一个逻辑中,同时需要调用到几个类,这时就可以将这几个类放入到一个中介类中,只依赖这一个中介类。这就减少了类之间的依赖,缺点就在于中介类是几个类的集合,这多少有些显得有些冗余。如果在类设计时出现了网状的类图,这个时候就需要考虑使用Mediator模式减少类与类之间的依赖。
Mediator的UML图如下:
Mediator:Colleage对象交互接口。
ConcreteMediator: 实现合作行为,协调Colleage对象,维护Colleage之间的联系。
Colleage:Colleage对象应该知道中介类,并且需要通过中介类与其他的Colleage对象进行交互。
列举一个简单的例子,写字板上的字体控件,通常是由两个下拉列表组成,更改字体样式跟更改字体大小,样式跟大小的改变都会导致Notepad文本的样式发生变化,我们分析这样的一个场景,会有Notepad类,Notepad类中包含FontListBox类,SizeListBox类还有保存内容的Content类,这个Content类会根据FontListBox、SizeListBox的选择来改变内容,这个就需要Notepad类知道所有的其他类,通常时序会像这样,Notepad调用FontListBox改变Font样式,然后Notepad调用Content改变样式,再调用SizeListBox改变大小,再调用Content改变样式。
这个示例中,逻辑还算清晰,不会有FontListBox与Notepad Content这样的交互,Meidator模式最适用于解决类与类之间网状交互的情形,可以用Mediator模式把环状的模式改变成星状的交互,使得所有的类只依赖Mediator类与其他类进行交互,复杂的逻辑也在mediator类中实现。
下面我们应用用mediator模式后,更改设计如下:
其中, aFontDialogDirector是mediator的作用,Notepad只与Director类产生关系,在调用玩setFont()与setSize()后,会回调到onFontChanged()这个函数,Notepad中只需要继承anEntryField,响应onFontChanged事件,调用aFontDialogDirector去改变字体就行了,不用再去了解FontDialog内部的逻辑了。
改进后的时序
了解了这么多,下面是Mediator模式在Pandora中的应用。
在Pandora中,Mediator模式的应用随处可见,基本上所有Pandora中可操作的对象都封装成mediator的调用,像ArtworkMediator,GuideMediator,MarkMediator,PressSheetMediator,StepRepeatMediator,以GuideMediator为例,其设计类图如下。
GuideMover相当于一个Client,是调用者的身份,GuideMediator处理所有的GuideGlyph(显示),与GuideConstraint(拖拽吸附) 的逻辑,在UpdatePosition时,GuideGlyph重绘,与Constraint值重新计算,很好的隔离了GuideMover这个类与GuideGlyph与GuideConstraint。
虽然使用Mediator模式会产生代码的冗余,但是却带来了代码更清晰的好处,权衡利弊,在合适的地方使用Mediator模式。
中介者模式的实际应用:
MVC框架:MVC框架中的C(Controller)其实就是一个中介者,作用就是把M和V隔离开,协调M和V的工作,这也是中介者优点的一个体现。
源码附件:
https://pan.baidu.com/s/13uOI7RHsNjbCxX4AA4_atA