“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” – GoF
用一个中介对象来封装一系列的对象交互。Mediator使各对象不需要显示的相互引用,从而使其耦合松散,以便可以独立地改变他们之间的交互。
Object-oriented design encourages the distribution of behavior among objects. Such distribution can result in an object structure with many connections between objects; in the worst case, every object ends up knowing about every other.
Though partitioning a system into many objects generally enhances reusability, proliferating interconnections tend to reduce it again. Lots of interconnections make it less likely that an object can work without the support of others—the system acts as though it were monolithic. Moreover, it can be difficult to change the system's behavior in any significant way, since behavior is distributed among many objects. As a result, you may be forced to define many subclasses to customize the system's behavior.
在软件构建过程中,经常会出现多个对象相互关联交互的情况,对象之间常常会维持一种复杂的引用关系,如果遇到一些需求的更改,这种直接的引用关系将面临不断的变化。在这种情况下,我们可以使用一个“中介对象”来管理对象间的关联关系,避免相互交互的对象之间的紧耦合的引用关系,从而更好地驾驭变化。
依赖关系的转化示例:
1. 5个类相互之间两两相互依赖; 1. 5各类彼此之间没有直接的依赖关系;
2. 共有10个关系需要维护; 2. 共有5个关系需要维护;
3. 如果任意其中一个类发生了改 3. 如果任意其中一个类发生了改变,那么
变,那么另外4个类,度需要 只需要修改Mediator即可,其它4个
随之改变; 类可以维持不变;
4. 如果要增加一个新类F,那么需要 4. 如果要增加一个类F,那么要维护的关系
维护的关系数量将变为15,并且 数量将变为6,原有的5个类不需要做任
原有的5个类均需要做相应改变。 和改变,仅需改变Mediator即可。
Applicability:
- A set of objects communicate in well-defined but complex ways. The resulting interdependencies are unstructed and difficult to understand.
- Resuing an object is difficult because it refers to and communicates with many other objects.
- A behavior that’s distributed between several classes should be customizable without a lot of subclassing.
Participants:
- Mediator:
Defines an interface for communicating with Colleague objects.
- ConcreteMediator:
Implements cooperative behavior by coordinatiing Colleague objects.
Knows and maintains its colleagues.
- Colleagues
Each Colleague class knows its Mediator object.
Each colleague communicates with its mediator whenever it would have otherwise communicated with another colleague.
业务示例:假定有如下图所示的界面:
RadioButtons包含了4个单选,CheckBoxes包含了4个复选框,ComboBox中有4个选项。先假定:
如果RadioButtons中选择了Roption1,那么CheckBoxes中的Coption1就会被选中,ComboBox中的ComOption1就会被选中;如果CheckBoxes中的COption1被选中,那么RadioButtons中的ROption1和ComboBox中的ComOption1就会被选中;如果ComboBox中的ComOption1被选中,那么RadioButtons中的ROption1和CheckBoxes中的Coption1就会被选中。以此类推。另外在这里,RadioButtons和其中的单选按钮被看成是一个对象,4个单选按钮可视为RadioButtons的4个状态;CheckBoxes和ComboBox也是如此。
还有一个假设:
CheckBoxes和ComboBox分别只能选择其中一项(即“复选框”也不能“复选”,与其实际功能不符,纯为研究用)
优点:
- 将多对多的关系转化为一对多的关系,使对象之间的关系更易于维护;
- 将对象的行为和协作抽象化。
缺点:
- 虽然降低了同事类的复杂性,但增加了调停者对象的复杂性;
- 同事类的复用性是以调停者类的不可复用为代价的。
C++实现代码:
// Mediator.h
#include <string>
#include <iostream>
using namespace std;
// 前置声明
class AbstractColleague;
// 抽象调停类
class AbstractMediator
{
public:
// 通知"同事"类,其参数aac为引发事件的对象
virtual void notify_colleagues(AbstractColleague *aac) = 0;
public:
virtual ~AbstractMediator()
{
cout << "in the destructor of AbstractMediator..." << endl;
}
};
// 抽象"同事"类
class AbstractColleague
{
protected:
AbstractMediator *mediator;
public:
AbstractColleague(AbstractMediator *mediator)
{
this->mediator = mediator;
}
~AbstractColleague()
{
cout << "in the destructor of AbstractColleague..." << endl;
}
public:
virtual void set_item_true(int i) = 0;
virtual int get_true_item() = 0;
void on_change(AbstractColleague *aac)
{
mediator->notify_colleagues(aac);
}
};
// 单选按钮
class RadioButtons : public AbstractColleague
{
private:
bool rButton1;
bool rButton2;
bool rButton3;
bool rButton4;
public:
RadioButtons(AbstractMediator *mediator) : AbstractColleague(mediator)
{
rButton1 = false;
rButton2 = false;
rButton3 = false;
rButton4 = false;
}
~RadioButtons()
{
cout << "in the destructor of RadioButtons..." << endl;
}
public:
void set_item_true(int i)
{
rButton1 = false;
rButton2 = false;
rButton3 = false;
rButton4 = false;
switch(i)
{
case 1:
rButton1 = true;
break;
case 2:
rButton2 = true;
break;
case 3:
rButton3 = true;
break;
case 4:
rButton4 = true;
break;
default:
rButton1 = true;
}
}
int get_true_item()
{
if(rButton1) return 1;
if(rButton2) return 2;
if(rButton3) return 3;
if(rButton4) return 4;
return 1;
}
void onRadioButtonClick()
{
on_change(this);
}
};
// 复选框
class CheckBoxes : public AbstractColleague
{
private:
bool cBox1;
bool cBox2;
bool cBox3;
bool cBox4;
public:
CheckBoxes(AbstractMediator *mediator) : AbstractColleague(mediator)
{
cBox1 = false;
cBox2 = false;
cBox3 = false;
cBox4 = false;
}
~CheckBoxes()
{
cout << "in the destructor of CheckBoxes..." << endl;
}
public:
void set_item_true(int i)
{
cBox1 = false;
cBox2 = false;
cBox3 = false;
cBox4 = false;
switch(i)
{
case 1:
cBox1 = true;
break;
case 2:
cBox2 = true;
break;
case 3:
cBox3 = true;
break;
case 4:
cBox4 = true;
break;
default:
cBox1 = true;
}
}
int get_true_item()
{
if(cBox1) return 1;
if(cBox2) return 2;
if(cBox3) return 3;
if(cBox4) return 4;
return 1;
}
void onCheckBoxClick()
{
on_change(this);
}
};
// 下拉框
class ComboBox : public AbstractColleague
{
private:
bool cOpt1;
bool cOpt2;
bool cOpt3;
bool cOpt4;
public:
ComboBox(AbstractMediator *mediator) : AbstractColleague(mediator)
{
cOpt1 = false;
cOpt2 = false;
cOpt3 = false;
cOpt4 = false;
}
~ComboBox()
{
cout << "in the destructor of ComboxBox..." << endl;
}
public:
void set_item_true(int i)
{
cOpt1 = false;
cOpt2 = false;
cOpt3 = false;
cOpt4 = false;
switch(i)
{
case 1:
cOpt1 = true;
break;
case 2:
cOpt2 = true;
break;
case 3:
cOpt3 = true;
break;
case 4:
cOpt4 = true;
break;
default:
cOpt1 = true;
}
}
int get_true_item()
{
if(cOpt1) return 1;
if(cOpt2) return 2;
if(cOpt3) return 3;
if(cOpt4) return 4;
return 1;
}
void onComboBoxClick()
{
on_change(this);
}
};
// 具体调停类
class ConcreteMediator : public AbstractMediator
{
private:
RadioButtons* rbt;
CheckBoxes* cbx;
ComboBox* cbo;
public:
~ConcreteMediator()
{
cout << "in the destructor of ConcreteMediator..." << endl;
}
void set_colleagues(RadioButtons* rbt, CheckBoxes* cbx, ComboBox* cbo)
{
this->rbt = rbt;
this->cbx = cbx;
this->cbo = cbo;
}
void notify_colleagues(AbstractColleague *aac)
{
int i = aac->get_true_item();
rbt->set_item_true(i);
cbx->set_item_true(i);
cbo->set_item_true(i);
}
};
// Mediator.cpp
#include "Mediator.h"
int main(int argc, char **argv)
{
AbstractMediator* mediator = new ConcreteMediator();
RadioButtons* rbt = new RadioButtons(mediator);
CheckBoxes* cbx = new CheckBoxes(mediator);
ComboBox* cbo = new ComboBox(mediator);
dynamic_cast<ConcreteMediator*>(mediator)->set_colleagues(rbt, cbx, cbo);
// 下面两行模拟RadioButtons的onClick事件触发,并选中第个单选按钮
rbt->set_item_true(1);
rbt->onRadioButtonClick();
cout << "Event triggered by the No.1 item of RadioButtons" << endl;
cout << "rButton" << rbt->get_true_item() << " \tis selected!" << endl;
cout << "cBox" << cbx->get_true_item() << " \t\tis selected accordingly!" << endl;
cout << "cOpt" << cbo->get_true_item() << " \t\tis selected accordingly!" << endl;
cout << "------------------------------------------------------" << endl;
// 下面两行模拟CheckBoxes的onClick事件触发,并选中第个复选框
cbx->set_item_true(2);
cbx->onCheckBoxClick();
cout << "Event triggered by the No.2 item of CheckBoxes" << endl;
cout << "rButton" << rbt->get_true_item() << " \tis selected accordingly!" << endl;
cout << "cBox" << cbx->get_true_item() << " \t\tis selected!" << endl;
cout << "cOpt" << cbo->get_true_item() << " \t\tis selected accordingly!" << endl;
cout << "------------------------------------------------------" << endl;
// 下面两行模拟ComboBox的onClick事件触发,并选中第个选项
cbo->set_item_true(3);
cbo->onComboBoxClick();
cout << "Event triggered by the No.3 item of ComboBox" << endl;
cout << "rButton" << rbt->get_true_item() << " \tis selected accordingly!" << endl;
cout << "cBox" << cbx->get_true_item() << " \t\tis selected accordingly!" << endl;
cout << "cOpt" << cbo->get_true_item() << " \t\tis selected!" << endl;
cout << "------------------------------------------------------" << endl;
delete mediator;
delete rbt;
delete cbx;
delete cbo;
return 0;
}
运行结果:
Event triggered by the No.1 item of RadioButtons
rButton1 is selected!
cBox1 is selected accordingly!
cOpt1 is selected accordingly!
------------------------------------------------------
Event triggered by the No.2 item of CheckBoxes
rButton2 is selected accordingly!
cBox2 is selected!
cOpt2 is selected accordingly!
------------------------------------------------------
Event triggered by the No.3 item of ComboBox
rButton3 is selected accordingly!
cBox3 is selected accordingly!
cOpt3 is selected!
------------------------------------------------------
in the destructor of ConcreteMediator...
in the destructor of AbstractMediator...
in the destructor of RadioButtons...
in the destructor of AbstractColleague...
in the destructor of CheckBoxes...
in the destructor of AbstractColleague...
in the destructor of ComboxBox...
in the destructor of AbstractColleague...
上述程序的UML类图: