中介者模式(Mediator) 从最初的代码一步步改进
动机:
● 在软件构建过程中,经常会出现多个对象互相关联交互的情况,对象之间常常会维持一种复杂的引用关系,如果遇到一些需求的更改,这种直接的引用关系将面临不断地变化。
● 在这种情况下,我们可以使用一个“中介对象”来管理对象间的关联关系,避免相互交互的对象之间的紧耦合引起关系,从而更好地抵御变化。
Mediator模式定义::用一个中介者对象来封装(封装变化)一系列的对象交互。中介者使各对象不需要显式的相互引用(编译时依赖—>运行时依赖),从而使其耦合松散(管理变化),而且可以独立地改变它们之间的交互。
中介者模式结构图:
Mediator通过这种方式将多对多的通信简化为了一(Mediator)对多(Colleague)的通信。
中介者模式主要包括以下几个类:
● Colleague是抽象同事类,CorrectColleague是具体同时类,每个具体同事只知道自己的行为,而不了解其他同事类的情况,但是他们都认识自己的中介者对象;
● Mediator是抽象中介者,定义了同事对象到中介者对象的接口,ConcreteMediator是具体中介者对象,实现抽象类的方法,它需要知道所有具体同事类,并从具体同事接收消息,向具体同事对象发出命令。
Mediator通过这种方式将多对多的通信简化为了一(Mediator)对多(Colleague)的通信。
//抽象同事类
abstract class Colleague
{
protected Mediator mediator;
//构造方法,得到中介者
public Colleague(Mediator mediator)
{
this.mediator = mediator;
}
}
//抽象中介者类
abstract class Mediator
{
//定义一个抽象的发送消息方法,得到同事消息和发送的消息
//colleague发送message
public abstract void Send(String message,Colleague colleague)
}
//具体同事类1
class ConcreteColleague1 extends Colleague
{
public ConcreteColleague1(Mediator mediator)
{super(mediator);}
public void Send(String message)
{
mediator.Send(message,this);//ConcreteColleague1发送message
}
public void Notify(String message)
{
System.out.println("同事1得到消息:"+message);
}
}
//具体同事类2
class ConcreteColleague2 extends Colleague
{
public ConcreteColleague2(Mediator mediator)
{super(mediator);}
public void Send(String message)
{
mediator.Send(message,this);//ConcreteColleague2发送message
}
public void Notify(String message)
{
System.out.println("同事2得到消息:"+message);
}
}
//具体中介者类
class ConcreteMediator extends Mediator
{
//需要了解所有的具体同事对象
private ConcreteColleague1 colleague1;
private ConcreteColleague2 colleague2;
public ConcreteColleague1 getColleaguge1()
{
return colleague1;
}
public void setColleague1(ConcreteColleague1 conlleague1)
{
this.colleague1 = conleague1;
}
public ConcreteColleague2 getColleaguge1()
{
return colleague2;
}
public void setColleague2(ConcreteColleague2 conlleague2)
{
this.colleague2 = conleague2;
}
//重写发送消息的方法,根据对象作出选择判断,通知具体同事对象
public void Send(String message,Colleague colleague)
{
//如果colleague1发送消息,则将消息通知colleague2
if(colleague == conleague1)
{colleague2.Notify(message);}
else
{colleague1.Notify(message);}
}
}
客户端
//客户端
public class program
{
public static void main(String[] args)
{
ConcreteMediator m = new ConcreteMediator();
//让两个具体同事类认识中介者对象
ConcreteColleague1 c1 = new ConcreteColleague1(m);
ConcreteColleague2 c2 = new ConcreteColleague2(m);
//让中介者认识各个具体同事类
m.setColleague1(c1);
m.setColleague1(c2);
//具体同事类对象发送消息都是通过中介者转发
c1.Send("吃饭了吗?");//找个人一起吃饭
c2.Send("没有呢,一起?");
}
}
中介者模式中,中介者对象定义了整个系统中所有具体同事类之间的关系,处于核心地位。在整个系统中它主要承担两个方面的任务:
1.结构上起到中转作用。通过中介者对象对关系的封装,使得具体的同事类不再需要显示的引用其他对象,通过中介者就可以完成与其他同事类之间的通信。
2.行为上起到协作作用。中介者对同事类之间的关系进行封装,同事类在不需要知道其他对象的情况下通过中介者与其他对象完成通信。在这个过程中同事类不需要知名中介者该如何做,中介者可以根据自身的逻辑进行协调,对同事的请求进一步处理,将同事成员之间的关系行为进行分离和封装。
由于有了Mediator对对象的关系进行了封装,使得ConcreteColleague1和ConcreteColleague2在发送消息和接收消息时通过中介者来完成,减少了同事类之间的耦合度,使得他们可以独立改变和复用。
中介者模式的实现——安理会做中介
代码结构图:
联合国机构类—Mediator类
//联合国机构
abstract class UnitedNations
{
//声明
public abstract void Declare(string message,Country colleague);
}
国家类—Colleague类
//国家
abstract class Country
{
protected UnitedNations mediator;
public Country(UnitedNations mediator)
{
this.mediator = mediator;
}
}
美国类—ConcreteColleague类
//美国
class USA extends Country
{
public USA(UnitedNations mediator)
{super(mediator);}
//声明
public void Declare(String message)
{mediator.Declare(message,this);}
//获取信息
public void GetMessage(String message)
{System.out.println("美国获得对方消息:"+message);}
}
伊拉克类—ConcreteColleague类
//伊拉克
class Iraq extends Country
{
public Iraq(UnitedNations mediator)
{super(mediator);}
//声明
public void Declare(String message)
{mediator.Declare(message,this);}
//获取信息
public void GetMessage(String message)
{System.out.println("伊拉克获得对方消息:"+message);}
}
联合国安理会—ConcreteColleague类
//联合国安全理事会
class UnitedNationSecurity extends UnitedNations
{
private USA colleague1;
private Iraq colleague2;
//美国
public USA getColleague1(){return colleague1;}
public void setColleague1(USA colleague1){this.colleague1 = colleague1;}
//伊拉克
public Iraq getColleague2(){return colleague2;}
public void setColleague2(USA colleague2){this.colleague2 = colleague2;}
public void Declare(String message,Country colleague)
{
if(colleague == colleague1)
{
colleague2.GetMessage(message);
}
else
{
colleague1.GetMessage(message);
}
}
}
public class Program
{
//客户端代码
public static void main(String[] args)
{
UnitedNationSecurity UNSC = new UnitedNationSecurity();
USA c1 = new USA(UNSC);
Iraq c2 = new Iraq(UNSC);
UNSC.setColleague1(c1);
UNSC.setColleague2(c2);
c1.Declare("不准研发核武器,否则开战");
c2.Declare("没研发,开战就开战");
}
}
结果:
伊拉克获得对方消息:不准研发核武器,否则开战
美国获得对方消息:没研发,开战就开战
优点:
● Mediator模式是一种很有用并且很常用的模式,它将对象间的通信封装到一个类中,将多对多的通信转化为一对多的通信,降低了系统的复杂性。
● Mediator还获得系统解耦的特性,通过Mediator,各个Colleague就不必维护各自通信的对象和通信协议,降低了系统的耦合性,Mediator和各个Colleague就可以相互独立地修改了。
● 将控制集中,便于管理。
缺点: 控制的集中化把交互复杂性变成了中介者的复杂性,这就使得中介者会变得比任何一个ConcreteColleague都复杂。
本质: 封装交互