设计模式--14、中介者模式
定义:用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互。
类型:行为类模式
看看结构图的形象描述吧:

中介者模式的结构
中介者模式又称为调停者模式,从类图中看,共分为3部分:
- 抽象中介者:定义好同事类对象到中介者对象的接口,用于各个同事类之间的通信。一般包括一个或几个抽象的事件方法,并由子类去实现。
- 中介者实现类:从抽象中介者继承而来,实现抽象中介者中定义的事件方法。从一个同事类接收消息,然后通过消息影响其他同时类。
- 同事类:如果一个对象会影响其他的对象,同时也会被其他对象影响,那么这两个对象称为同事类。在类图中,同事类只有一个,这其实是现实的省略,在实际应用中,同事类一般由多个组成,他们之间相互影响,相互依赖。同事类越多,关系越复杂。并且,同事类也可以表现为继承了同一个抽象类的一组实现组成。在中介者模式中,同事类之间必须通过中介者才能进行消息传递。
为什么要使用中介者模式
一般来说,同事类之间的关系是比较复杂的,多个同事类之间互相关联时,他们之间的关系会呈现为复杂的网状结构,这是一种过度耦合的架构,即不利于类的复用,也不稳定。例如在下图中,有六个同事类对象,假如对象1发生变化,那么将会有4个对象受到影响。如果对象2发生变化,那么将会有5个对象受到影响。也就是说,同事类之间直接关联的设计是不好的。


如果引入中介者模式,那么同事类之间的关系将变为星型结构,从图中可以看到,任何一个类的变动,只会影响的类本身,以及中介者,这样就减小了系统的耦合。一个好的设计,必定不会把所有的对象关系处理逻辑封装在本类中,而是使用一个专门的类来管理那些不属于自己的行为。

对于设计模式这个东西,理解了,应该写一个代码体会一下,我们以qq和email发送消息为实例,代码如下:
package designpatterns;
import java.util.HashMap;
import java.util.Map.Entry;
/*
* 中介者模式
*/
//先抽像一个使用者类(学生)
abstract class Person {
String strName; //姓名
String strType; //类型
//每个人都有一个用来传递信息的中介List,如qq,email等
HashMap<String, AbstractMediator> MyMediatorList = new HashMap<String, AbstractMediator>();
public Person(String strName){
this.strName = strName;
}
public String getStrName() {
return strName;
}
public void setStrName(String strName) {
this.strName = strName;
}
public String getStrType() {
return strType;
}
public void setStrType(String strType) {
this.strType = strType;
}
public void AddMediator(AbstractMediator MyMediator) {
MyMediatorList.put(MyMediator.getStrName(), MyMediator);
}
//给所有人发消息
public void SendMessageToAll(String MediatorName, String strMessage){
MyMediatorList.get(MediatorName).SendMessageToAll(strMessage);
}
//给指定类型的人发消息
public void SendMessageByType(String MediatorName, String strType, String strMessage) {
MyMediatorList.get(MediatorName).SendMessageByType(strType, strMessage);
}
//给指定名字的人发消息
public void SendMessageByName(String MediatorName, String strName, String strMessage) {
MyMediatorList.get(MediatorName).SendMessageByName(strName, strMessage);
}
//接收消息
public void ReciveMessage(String strMessage){
System.out.println("[" + strType +"]" + "\"" + strName + "\"" + "收到"+strMessage);
}
}
//定义学生
class Student extends Person {
public Student(String strName) {
super(strName);
strType = "学生";
}
}
//定义老师
class Teacher extends Person {
public Teacher(String strName) {
super(strName);
strType = "老师";
}
}
//定义校长
class Principal extends Person {
public Principal(String strName) {
super(strName);
strType = "校长";
}
}
//定义一个抽象中介
abstract class AbstractMediator {
//中介的名字
String strName;
public AbstractMediator (String strName) {
this.strName = strName;
}
public String getStrName() {
return strName;
}
//定义一个人员列表
HashMap<String, Person> PersonList = new HashMap<String, Person>();
public void addPerson(Person onePerson) {
PersonList.put(onePerson.getStrName(), onePerson);
onePerson.AddMediator(this);
}
public void deletePerson(String strName) {
PersonList.remove(strName);
}
//给所有人发消息
abstract public void SendMessageToAll(String strMessage);
//给指定类型的人发消息
abstract public void SendMessageByType(String strType, String strMessage);
//给指定名字的人发消息
abstract public void SendMessageByName(String strName, String strMessage);
}
//定义一个中介(QQ)用于传递消息
class QQMediator extends AbstractMediator{
public QQMediator(String strName) {
super(strName);
}
@Override
public void SendMessageToAll(String strMessage) {
String strQQMessage = "来自QQ消息:" + strMessage;
for(Entry<String, Person> entry : PersonList.entrySet()){
entry.getValue().ReciveMessage(strQQMessage);
}
}
@Override
public void SendMessageByType(String strType, String strMessage) {
String strQQMessage = "来自QQ消息:" + strMessage;
for(Entry<String, Person> entry : PersonList.entrySet()){
if(strType == entry.getValue().getStrType())
{
entry.getValue().ReciveMessage(strQQMessage);
}
}
}
@Override
public void SendMessageByName(String strName, String strMessage) {
String strQQMessage = "来自QQ消息:" + strMessage;
PersonList.get(strName).ReciveMessage(strQQMessage);
}
}
//定义一个中介(Email)用于传递消息
class EmailMediator extends AbstractMediator{
public EmailMediator(String strName) {
super(strName);
}
@Override
public void SendMessageToAll(String strMessage) {
String strQQMessage = "来自Email消息:" + strMessage;
for(Entry<String, Person> entry : PersonList.entrySet()){
entry.getValue().ReciveMessage(strQQMessage);
}
}
@Override
public void SendMessageByType(String strType, String strMessage) {
String strQQMessage = "来自Email消息:" + strMessage;
for(Entry<String, Person> entry : PersonList.entrySet()){
if(strType == entry.getValue().getStrType())
{
entry.getValue().ReciveMessage(strQQMessage);
}
}
}
@Override
public void SendMessageByName(String strName, String strMessage) {
String strQQMessage = "来自Email消息:" + strMessage;
PersonList.get(strName).ReciveMessage(strQQMessage);
}
}
public class Mediator {
public static void main(String[] args) {
//定义两个学生
Student student1 = new Student("学生一");
Student student2 = new Student("学生二");
//定义两个老师
Teacher teacher1 = new Teacher("老师一");
Teacher teacher2 = new Teacher("老师二");
//定义两个校长
Principal principal1 = new Principal("校长一");
Principal principal2 = new Principal("校长二");
//定义两个中介(QQ和email)
QQMediator myQQ = new QQMediator("qq");
EmailMediator myEmail = new EmailMediator("email");
//将所有人员分别添加到qq和email中
myQQ.addPerson(student1);
myQQ.addPerson(student2);
myQQ.addPerson(teacher1);
myQQ.addPerson(teacher2);
myQQ.addPerson(principal1);
myQQ.addPerson(principal2);
myEmail.addPerson(student1);
myEmail.addPerson(student2);
myEmail.addPerson(teacher1);
myEmail.addPerson(teacher2);
myEmail.addPerson(principal1);
myEmail.addPerson(principal2);
//下面开始进行通信
//首先"校长一"通过qq向"校长二"发一条消息
principal1.SendMessageByName("qq", "校长二", "你觉得什么时候放假好?");
principal2.SendMessageByName("qq", "校长一", "从明天开始放假吧!");
principal1.SendMessageByName("qq", "校长二", "好的,那我发通知了");
//然后"校长一"通过email向所有人员发一条消息
principal1.SendMessageByType("email", "老师", "老师们都注意了,从明天开始放假");
//老师收到消息后再给学生发消息
teacher1.SendMessageByType("email", "学生", "同学们都注意了,从明天开始放假了!");
//学生收到消息后,开始qq聊起来了
student1.SendMessageByName("qq", "学生二", "明天放假了,我们去哪玩啊?");
student2.SendMessageByName("qq", "学生一", "我们去爬山吧,再问问还有没有别人去!");
student2.SendMessageToAll("email", "明天我们去爬山,还有没有一起去的?");
}
}
二、使用中介者模式的场合和优缺点
使用终结者模式的场合
1.一组定义良好的对象,现在要进行复杂的通信。
2.定制一个分布在多个类中的行为,而又不想生成太多的子类。
可以看出,中介对象主要是用来封装行为的,行为的参与者就是那些对象,但是通过中介者,这些对象不用相互知道。呵呵~~~
使用中介者模式的优点:
1.降低了系统对象之间的耦合性,使得对象易于独立的被复用。
2.提高系统的灵活性,使得系统易于扩展和维护。
使用中介者模式的缺点:
中介者模式的缺点是显而易见的,因为这个“中介“承担了较多的责任,所以一旦这个中介对象出现了问题,那么整个系统就会受到重大的影响。

浙公网安备 33010602011771号