意图
用一个中介对象来封装一系列对象的交互。中介者使得各对象不需要显式相互引用,从而使其松散耦合,而且可以独立地改变它们之间的交互。
Mediator模式解决了一个问题,多个类相互引用相互,相互影响,这时候类的关系模型是复杂的,一个类对象的变化会导致其他类对象的变化,这种场景有点连锁反应的意思。下面有一段代码
- class CutMenuItem
- {
- TextArea textArea;
- ClipBorad clipBorad;
- ToolBarButton toolBarButton;
- public void Click()
- {
- string text = textArea.SelectedText;
- textArea.RemoveSelectionText();
- clipBorad.SetData(text);
- toolBarButton.EnabledPasteButton();
- }
- }
- class TextArea
- {
- ClipBorad clipBoard;
- ToolBarButton toolBarButton;
- CutMenuItem cutMenuItem;
- internal void RemoveSelectionText()
- {
- }
- }
- class ClipBorad
- {
- ToolBarButton toolBarButton;
- CutMenuItem cutMenuItem;
- TextArea textArea;
- internal void SetData(string text)
- {
- }
- }
- class ToolBarButton
- {
- ClipBorad clipBorad;
- CutMenuItem cutMenuItem;
- TextArea textArea;
- internal void EnabledPasteButton()
- {
- }
- }
上面有四个类:菜单、文本框、按钮、剪贴板,每个类里面都包含其他三个类的引用。当每个类的某个方法被调用时,会连锁的引起其他三个类的对象的方法的调用。如果我们按照这种方式来写的话,如果类比较多,我们会陷入一种混乱状态。我们需要一种设计模式,将他们进行解藕。因此我们使用Mediator设计模式
- abstract class Mediator
- {
- public abstract void Notify();
- public virtual void AddElement(Element element)
- {
- list.Add(element);
- }
- List<Element> list = new List<Element>();
- }
- abstract class Element
- {
- Mediator mediator;
- public Element(Mediator mediator)
- {
- this.mediator = mediator;
- this.mediator.AddElement(this);
- }
- public virtual void OnChange()
- {
- }
- }
- class TextArea : Element
- {
- public TextArea(Mediator mediator) : base(mediator)
- {
- }
- public void Process()
- {
- OnChange();
- }
- }
- class CutMenuItem : Element
- {
- public CutMenuItem(Mediator mediator) : base(mediator)
- {
- }
- public void Click()
- {
- OnChange();
- }
- }
- class ClipBoard : Element
- {
- public ClipBoard(Mediator mediator) : base(mediator)
- {
- }
- public void Invoke()
- {
- OnChange();
- }
- }
- class ToolBarButton : Element
- {
- public ToolBarButton(Mediator mediator) : base(mediator)
- {
- }
- public void Click()
- {
- OnChange();
- }
- }
- class ConcreteMediator : Mediator
- {
- public override void Notify()
- {
- }
- }
在代码里面我们抽象了Mediator类,他有一个List的内部成员用来保存按钮、菜单等对象,有一个抽象方法Notify。我们又抽象了一个Element类,这个类有一个构造函数将指定的中介者保存在内部成员里面,并将自己加入到Mediator对象的List列表里。在Element类里还有一个OnChange的虚方法,可由派生类重写。
菜单、按钮、剪贴板、文本框都继承Element类。那么我们在实例化菜单等对象的时候,将他们几种在了一个mediator对象的List里。也就是说,我们在菜单等对象构造的时候我们就将它们转换到mediator里面去了,这就是在解藕。那当我们的菜单等对象动作的时候,我们就可以直接调用基类的OnChange方法,那么我们就可以在Element类的OnChange方法里面遍历mediator里面的List中的元素来调用对应的方法。这里有一个问题,我们为什么要抽象Mediator,我们完全可以不用抽象Mediator,直接可以用一个具体的类来实现,但是,这是在理想的情况,我们不是简单的关联关系,我们不会仅仅只有四个类型进行关联,我们可能有很多其他的对象需要关联,如果我们直接写到一个具体的类里面,那么我们的Notify方法会相当的复杂,会写很多if语句进行判断。比如说当按钮点击,我们调用List里面的ABC三个对象的方法,当菜单点击,我们会调用BCD三个对象的另外的方法,如果这样扩展下去,Notify方法将相当庞大。所以,我们可以将mediator类进行抽象,由ConcreteMediator类来实现各自的具体的逻辑,比如说当按钮点击,我可以知道这是一个联动操作的mediator,将他封装成一个类,在实现的Notify方法里面可以调用ABC的方法,当菜单点击我们可以实现另外一个mediator类,在他的Notify方法里,调用BCD的方法。
如果一组接口相对稳定的对象之间的依赖关系错综复杂,依赖关系难以维护,或者会发生变动可以考虑引入中介者模式。
我们对比一下facade模式
facade模式是几个小对象组成一个大对象,如汽车这个对象里包含轮子、方向盘等对象,汽车就是轮子等对象的外观,我们将轮子封装到汽车里,并且将他们的方法提供到汽车对象里。
Facade模式是解藕系统外到系统内(单向)的对象关联关系;mediator模式是解藕系统内各个对象之间(双向)的关联关系