中介者(Mediator)
中介者模式属于设计模式::行为模式的一种,特别的,属于行为对象模式。
行为模式涉及到算法和对象间职责的分配。行为模式不仅描述对象或类的模式,还描述他们之间的通信模式(协作)。
行为模式分为两种:
- 行为类模式:使用继承机制在类间分配行为。
- 行为对象模式:使用对象复合而不是继承。
一言以蔽之
引入一个中间对象(中介),解决对象间的(双向)依赖,避免紧耦合(接口隔离)。
注:门面模式(Facade)解决系统间单向的依赖。
举例
/*
* 窗口对话框的基类
*/
class Director{
public:
virtual ~Director();
virtual void WidgetChanged(Widget*) = 0;
protected:
Director();
virtual void CreateWidgets() = 0;
}
/*
* 控件的基类
*/
class Widget{
public:
Widget(Director*);
virtual void Changed(){
// 在这里调用Director的接口方法,Director的子类为窗口
_director->WidgetChanged();
}
// 规范接口
virtual void HandleMouseEvent(MouseEvent& event);
private:
Director* _director;
}
class ListBox : public Widget{
public:
ListBox(Director*);
virtual const char* GetSelection();
virtual void SetList(List<char*>* listItems);
virtual void HandleMouseEvent(MouseEvent& event) override{}
}
class EntryField : public Widget{
public:
EntryField(Director*);
virtual const char* GetText();
virtual void SetText(const char* text);
virtual void HandleMouseEvent(MouseEvent& event) override {}
}
class Button : public Widget{
public:
Button(Director*);
virtual void SetText(const char* text);
virtual void HandleMouseEvent(MouseEvent& event) override {
// ...
Changed(); // 基类方法
}
}
/*
* 使用控件组装对话框,这个就是中介者(沟通各个控件)
*/
class FontDirector : public Director{
public:
FontDirector();
virtual ~FontDirector();
// 保证窗口组件正确协同工作
virtual void WidgetChanged(Widget* theChangedWidget) override{
if (theChangedWidget == _fontListBox) {
_fontNameField->SetText(_fontListBox->GetSelection());
} else if (theChangedWidget == _okButton){
// ...
} else if (theChangedWidget == _cancelButton){
// ...
}
}
protected:
virtual void CreateWidgets() override{
_okButton = new Button(this);
//...
// 把这些控件放到对话框中
}
private:
Button* _okButton;
Button* _cancelButton;
ListBox* _fontListBox;
EntryField* _fontNameField;
}
注意事项
中介者中的M需要一种消息通知的规范,好与所有的依赖对象进行沟通。
Widget::Changed(),Widget的子类可以调用此方法与FontDirector对象进行沟通,通知FontDirector进行更新界面。Widget::HandleMouseEvent()=0,应用程序需要把系统事件(如鼠标点击事件)分发给应用程序内不同的GUI对象,这里实现事件循环的对象(分发系统事件的对象,如EventDispatch类)也是一个中介者,而HandleMouseEvent就是一个消息接口规范。
混合模式:中介者+观察者
- 观察者模式:有Event的时候通知Observer,可以有多个Observer。比如QT中的:(继承QObejct的时候会注册)
void paintEvent(QPaintEvent *) override;
void mouseMoveEvent(QMouseEvent *) override;
- 中介者模式:使用
EventDispatch类处理Event与Event之间的处理逻辑。
使用场景
数据绑定类型:同时依赖界面元素、数据模型
数据模型改变,绑定的对象(可以理解为中介者)就得到消息,去更改界面元素
中介者与观察者的区别
- 都是行为对象模式(对象行为模式)。
- 中介者强调是多个类(同事类)之间的交互,多对多,通过一个中介者来交互。
- 观察者强调一对多的关系,一个变化,其他都变化
相关模式
- 门面模式(Facade)
- 观察者模式(Observer)