转自:http://liulinqi206.blog.163.com/blog/static/13460476620120173323449/
一、什么是中介者模式
Mediator模式也叫中介者模式,是由GoF提出的23种软件设计模式的一种。Mediator模式是行为模式之一,在Mediator模式中,类之间的交互行为被统一放在Mediator的对象中,对象通过Mediator对象同其他对象交互,Mediator对象起着控制器的作用
在Mediator模式中,每一个Colleague维护一个Mediator,交互的时候可以通过ConcreteMediator的子函数进行处理。
class Mediator;
class Colleage
{
public:
protected:
};
class ConcreteColleageA:public Colleage
{
public:
private:
};
class ConcreteColleageB:public Colleage
{
public:
private:
};
class Mediator
{
public:
protected:
};
class ConcreteMediator:public Mediator
{
public:
private:
};
void ConcreteColleageA::Action()
{
}
void ConcreteColleageB::Action()
{
}
void main()
{
}
20. C++实现Behavioral - Mediator模式
2010-02-05 00:17:07| 分类: Pattern | 标签: |字号大中小 订阅
“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 beha
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 beha
在软件构建过程中,经常会出现多个对象相互关联交互的情况,对象之间常常会维持一种复杂的引用关系,如果遇到一些需求的更改,这种直接的引用关系将面临不断的变化。在这种情况下,我们可以使用一个“中介对象”来管理对象间的关联关系,避免相互交互的对象之间的紧耦合的引用关系,从而更好地驾驭变化。
依赖关系的转化示例:
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 beha
Participants:
- Mediator:
Defines an interface for communicating with Colleague objects.
- ConcreteMediator:
Implements cooperative beha
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 on
{
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 on
{
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 on
{
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的on
rbt->set_item_true(1);
rbt->on
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的on
cbx->set_item_true(2);
cbx->on
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的on
cbo->set_item_true(3);
cbo->on
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类图:
mediator
中介者类的抽象父类。
concreteMediator
具体的中介者类。
colleague关联类的抽象父类。
concreteColleague
具体的关联类。
四、中介者模式的优点
1. 将系统按功能分割成更小的对象,符合类的最小设计原则
2. 对关联对象的集中控制
3. 减小类的耦合程度,明确类之间的相互关系:当类之间的关系过于复杂时,其中任何一个类的修改都会影响到其他类,不符合类的设计的开闭原则 ,而Mediator模式将原来相互依存的多对多的类之间的关系简化为Mediator控制类与其他关联类的一对多的关系,当其中一个类修改时,可以对其他关联类不产生影响(即使有修改,也集中在Mediator控制类)。
4. 有利于提高类的重用性
描述经过Facade模式的改装后,一个子系统的使用端与子系统的关系。图中的大方框代表一个子系统。
就如同医院的接待员一样,Facade模式的门面类型将使用端与子系统的内部复杂性分隔开,使得使用端只需要与门面对象打交道,而不需要与子系统内部的很多对象打交道。
Mediator架构模式
Mediator模式包装了一系列对象相互作用的方式,使得这些对象不必互相明显参照;从而使它们可以较松散地耦合。当这些对象中的某些对象之间的相互作用发生改变时,不会立即影响到其它的一些对象之间的相互作用;从而可以保证这些相互作用可以彼此独立地变化。
在下面的示意图中有大量的对象,这些对象既会影响别的对象,又会被别的对象所影响,因此常常叫做同事(Colleague)对象。这些同事对象通过彼此的相互作用形成系统的行为。从图中可以看出,几乎每一个对象都需要与其它的对象发生相互作用,而这种相互作用表现为一个对象与另一个对象的直接耦合。
此主题相关图片如下:
图5、这是一个过度耦合的系统
通过引入调停者对象(Mediator),可以将系统的网状结构变成以中介者为中心的星形结构,如下图所示。在这个星形结构中,同事对象不再通过直接的联系与另一个对象发生相互作用;相反地,它通过调停者对象与另一个对象发生相互作用。调停者对象的存在保证了对象结构上的稳定,也就是说,系统的结构不会因为新对象的引入造成大量的修改工作。
此主题相关图片如下:
图6、这是一个使用了Mediator架构模式之后的结构图
比较传统的设计方法,面向对象的技术可以更好地协助设计师管理更为复杂的系统。一个好的面向对象的设计可以使对象之间增加协作性(Collaboration),减少耦合度(Coupling)。一个深思熟虑的设计会把一个系统分解为一群相互协作的同事对象,然后给每一个同事对象以独特的责任,恰当的配置它们之间的协作关系,使它们可以在一起工作。
在Mediator模式中,所有的成员对象都可以协调工作,但是又不直接相互管理。这些对象都与一个处于中心地位的调停者对象发生紧密的关系,由这个调停者对象进行协调工作。这个协调者对象叫做调停者(Mediator),而调停者所协调的成员对象称做同事(Colleague)对象。
在Colleague对象内部发生的事件会影响到所有的同事,但是这种影响不是以直接管理的方式直接传到其它的对象上的。记住在小组的成员增加时,这样的相互作用关系是以比指数更快的方式增加的。相反,这种影响仅仅直接影响到调停者对象,而调停者对象反过来会协调其它的同事,形成整个系统的行为。
如果小组的成员增加时,调停者对象可能会面临修改,而其它的同事则可以装做不知道这个新的成员一样,不必修改。反过来,如果小组的成员之一被从系统中删除的话,调停者对象需要对此做出修改,而小组中其它的同事则不必改动。
未运用中介模式前的实现:
Person.java
package com.ibeifeng.ex1; public abstract class Person { private String name; private int condition; public Person(String name, int condition) { this.name = name; this.condition = condition; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getCondition() { return condition; } public void setCondition(int condition) { this.condition = condition; } public abstract void getPartner(Person person); }
Man.java
package com.ibeifeng.ex1; public class Man extends Person { public Man(String name, int condition) { super(name, condition); } public void getPartner(Person person) { if(person instanceof Man) { System.out.println("汗,我不是同性恋!"); } else { if(this.getCondition() == person.getCondition()) { System.out.println(this.getName() + "和" + person.getName() + "绝配"); } else { System.out.println(this.getName() + "和" + person.getName() + "不相配"); } } } }
Woman.java
package com.ibeifeng.ex1; public class Woman extends Person { public Woman(String name, int condition) { super(name, condition); } public void getPartner(Person person) { if(person instanceof Woman) { System.out.println("汗,我不是同性恋!"); } else { if(this.getCondition() == person.getCondition()) { System.out.println(this.getName() + "和" + person.getName() + "绝配"); } else { System.out.println(this.getName() + "和" + person.getName() + "不相配"); } } } }
MainClass.java
package com.ibeifeng.ex1; public class MainClass { public static void main(String[] args) { Person zhangsan = new Man("张三",5); Person lisi = new Man("李四",6); Person xiaofang = new Woman("小芳", 6); zhangsan.getPartner(xiaofang); lisi.getPartner(xiaofang); zhangsan.getPartner(lisi); } }
运用了中介模式的代码:
Person.java
package com.ibeifeng.ex2; public abstract class Person { private String name; private int condition; private Mediator mediator; public Person(String name, int condition, Mediator mediator) { super(); this.name = name; this.condition = condition; this.mediator = mediator; } public Mediator getMediator() { return mediator; } public void setMediator(Mediator mediator) { this.mediator = mediator; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getCondition() { return condition; } public void setCondition(int condition) { this.condition = condition; } public abstract void getPartner(Person person); }
Man.java
package com.ibeifeng.ex2; public class Man extends Person { public Man(String name, int condition,Mediator mediator) { super(name, condition, mediator); } public void getPartner(Person person) { this.getMediator().setMan(this); this.getMediator().getPartner(person); } }
Woman.java
package com.ibeifeng.ex2; public class Woman extends Person { public Woman(String name, int condition,Mediator mediator) { super(name, condition, mediator); } public void getPartner(Person person) { this.getMediator().setWoman(this); this.getMediator().getPartner(person); } }
Mediator.java
package com.ibeifeng.ex2; public class Mediator { private Man man; private Woman woman; public void setMan(Man man) { this.man = man; } public void setWoman(Woman woman) { this.woman = woman; } public void getPartner(Person person) { //将搭档设置上 if(person instanceof Man) { this.setMan((Man)person); } else { this.setWoman((Woman)person); } //判断条件 if(man == null || woman == null) { System.out.println("汗,我不是同性恋!"); } else { if(man.getCondition() == woman.getCondition()) { System.out.println(man.getName() + "和" + woman.getName() + "绝配"); } else { System.out.println(man.getName() + "和" + woman.getName() + "不相配"); } } } }
MainClass.java
package com.ibeifeng.ex2; public class MainClass { public static void main(String[] args) { Mediator mediator = new Mediator(); Person zhangsan = new Man("张三",7,mediator); Person lisi = new Man("李四",7,mediator); Person xiaofang = new Woman("小芳",7,mediator); zhangsan.getPartner(lisi); xiaofang.getPartner(lisi);