1.1概述
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。这就是中介者模式的定义。
一个对象含有另一个对象的引用是面向对象中经常使用的方式,也是面向对象所提倡的,即少用继承多用组合。但是怎样合理地组合对象对系统今后的扩展、维护和对象的复用是至关重要的,这也正是学习设计模式的重要原因。
例如,在一个房屋租赁系统中,有很多对象,有些对象是求租者,有些是出租者,如果要求他们之间必须成为朋友才能进行有关租赁的操作,显然不利于系统的维护和发展,因此,每当有新的出租者或求租者加入该系统,这个新的加入者必须和现有系统中的所有人互为朋友后才能和他们进行有关租赁的操作,这就意味着要修改大量的代码,这对系统的维护是非常不利的也是无法容忍的。一个好的解决办法就是在房屋租赁系统中建立一个称作中介者的对象,中介者包含系统中所有其他对象的引用,而系统中的其他对象只包含中介者的引用,也就是说中介者和大家互为朋友、中介者使系统中的其他对象完全解耦,当系统中某个对象需要和系统中另外一个对象交互时,只需将自己的请求通知中介者即可,如果有新的加入者,该加入者只需含有中介者的引用,并让中介者含有自己的引用,他就可以和系统中其他对象进行有关租赁操作,具体如下图一所示:
图一:中介者、出租者和求租者
中介者模式是封装一系列的对象交互的成熟模式,其关键是将对象之间的交互封装在称作中介者的对象中,中介者使各对象不需要显示地相互吸引,这些对象只包含中介者的引用。当系统中某个对象需要和系统中另外一个对象交互时,只需要将自己的请求通知给中介者即可。
1.2模式的结构
中介者模式的结构包含四种角色:
(1)中介者(Mediator):中介者是一个接口,该接口定义了用于同事对象之间进行通信的方法。
(2)具体中介者(ConcreteMediator):具体中介者是实现中介者接口的类。具体中介者需要包含所有具体同事的引用,并通过实现中介者接口中的方法来满足具体同事之间的通信请求。
(3)同事(Colleague):一个接口,规定了具体同事需要实现的方法。
(4)具体同事(ConcreteColleague):实现同事接口的类。具体同事需要包含具体中介者的引用,一个具体同事需要和其他具体同事交互时,只需要将自己的请求通知给它所包含的具体中介者即可。
中介者模式结构的类图如下图二所示:
图二:中介者模式类图
1.3中介者模式的优点
(1)可以避免许多的对象为了通信而相互显示引用,否则,不仅系统难于维护,而且也使其他系统难以复用这些对象。
(2)可以通过中介者将原本分布于多个对象之间的交互行为集中在一起。当这些对象之间需要改变之间的通信行为时,只需要使用一个具体中介者即可,不必修改各个具体同事的代码,即这些同事可被重用。
(3)具体中介者使得各个具体同事完全解耦,修改任何一个具体同事的代码不会影响到其他同事。
(4)具体中介者集中了同事之间是如何交互的细节,使系统比较清楚地知道整个系统中的同事是如何交互的。
(5)当一些对象相互通信,但又无法相互包含对方的引用,那么使用中介者模式就可以使这些对象相互通信。
1.4适合使用中介者模式的情景
(1)许多对象以复杂的方式交互,所导致的依赖关系使系统难以理解和维护。
(2)一个对象引用其他很多对象,导致难以复用该对象。
1.5中介者模式的使用
以下通过一个简单的问题来描述中介者模式中所涉及的各个角色。
古代相互交战的A、B、C三方,想通过一个中介者调停之间的战火。A方委托调停者转达的信息是:“要求B方归还曾抢夺的100斤土豆,要求C方归还曾抢夺的20头牛”;B方委托调停者转达的信息是:“要求A方归还曾抢夺的10只公鸡,要求C方归还曾抢夺的15匹马”;C方委托调停者转达的信息是:“要求A方曾抢夺的360斤小麦,要求B方曾抢夺的50头驴”。
针对上述问题,使用中介者模式设计若干个类。具体如下:
首先看一下本实例构建框架具体类和1.2模式的结构中类图的对应关系,如下图所示:
(1)同事(Colleague)
本问题中,同事接口是Colleague,定义了具体同事,即交战各方需要实现的方法。Colleague接口的代码如下:
package com.liuzhen.nine_mediator; public interface Colleague { public void giveMess(String[] mess); public void receiverMess(String mess); public void setName(String name); public String getName(); }
(2)具体中介者(Mediator)
本问题中,只需要一个具体中介者,并不需要一个中介者接口,具体中介者是ConcreteMediator类,代码如下:
package com.liuzhen.nine_mediator; public class ConcreteMediator { ColleagueA colleagueA; ColleagueB colleagueB; ColleagueC colleagueC; public void registerColleagueA(ColleagueA colleagueA){ this.colleagueA = colleagueA; } public void registerColleagueB(ColleagueB colleagueB){ this.colleagueB = colleagueB; } public void registerColleagueC(ColleagueC colleagueC){ this.colleagueC = colleagueC; } public void deliveMess(Colleague colleague , String[] mess){ if(colleague == colleagueA){ if(mess.length >= 2){ colleagueB.receiverMess(colleague.getName()+mess[0]); colleagueC.receiverMess(colleague.getName()+mess[1]); } } if(colleague == colleagueB){ if(mess.length >= 2){ colleagueA.receiverMess(colleague.getName()+mess[0]); colleagueC.receiverMess(colleague.getName()+mess[1]); } } if(colleague == colleagueC){ if(mess.length >= 2){ colleagueA.receiverMess(colleague.getName()+mess[0]); colleagueB.receiverMess(colleague.getName()+mess[1]); } } } }
(3)具体同事(ConcreteColleague)
对于本问题。有ColleagueA、ColleagueB和ColleagueC三个具体同事,其实例分别表示交战的三方,代码如下:
ColleagueA.java
package com.liuzhen.nine_mediator; public class ColleagueA implements Colleague { ConcreteMediator mediator; //中介者 String name; ColleagueA(ConcreteMediator mediator){ this.mediator = mediator; mediator.registerColleagueA(this); } public void giveMess(String[] mess) { // TODO Auto-generated method stub mediator.deliveMess(this, mess); } public void receiverMess(String mess) { // TODO Auto-generated method stub System.out.println(name+"收到的消息:"); System.out.println(" "+mess); } public void setName(String name) { // TODO Auto-generated method stub this.name = name; } public String getName() { // TODO Auto-generated method stub return name; } }
ColleagueB.java
package com.liuzhen.nine_mediator; public class ColleagueB implements Colleague { ConcreteMediator mediator; //中介者 String name; ColleagueB(ConcreteMediator mediator){ this.mediator = mediator; mediator.registerColleagueB(this); } public void giveMess(String[] mess) { // TODO Auto-generated method stub mediator.deliveMess(this, mess); } public void receiverMess(String mess) { // TODO Auto-generated method stub System.out.println(name+"收到的消息:"); System.out.println(" "+mess); } public void setName(String name) { // TODO Auto-generated method stub this.name = name; } public String getName() { // TODO Auto-generated method stub return name; } }
ColleagueC.java
package com.liuzhen.nine_mediator; public class ColleagueC implements Colleague { ConcreteMediator mediator; //中介者 String name; ColleagueC(ConcreteMediator mediator){ this.mediator = mediator; mediator.registerColleagueC(this); } public void giveMess(String[] mess) { // TODO Auto-generated method stub mediator.deliveMess(this, mess); } public void receiverMess(String mess) { // TODO Auto-generated method stub System.out.println(name+"收到的消息:"); System.out.println(" "+mess); } public void setName(String name) { // TODO Auto-generated method stub this.name = name; } public String getName() { // TODO Auto-generated method stub return name; } }
(4)具体使用
通过NineApplication类来具体实现上述相关类和接口,来实现适配器模式的运用,其代码如下:
package com.liuzhen.nine_mediator; public class NineApplication { public static void main(String[] args){ ConcreteMediator mediator = new ConcreteMediator(); ColleagueA colleagueA = new ColleagueA(mediator); ColleagueB colleagueB = new ColleagueB(mediator); ColleagueC colleagueC = new ColleagueC(mediator); colleagueA.setName("A国"); colleagueB.setName("B国"); colleagueC.setName("C国"); String[] messA = {"要求B方归还曾抢夺的100斤土豆" , "要求C方归还曾抢夺的20头牛"}; colleagueA.giveMess(messA); String[] messB = {"要求A方归还曾抢夺的10只公鸡" , "要求C方归还曾抢夺的15匹马"}; colleagueB.giveMess(messB); String[] messC = {"要求A方曾抢夺的360斤小麦" , "要求B方曾抢夺的50头驴"}; colleagueC.giveMess(messC); } }
运行结果:
B国收到的消息:
A国要求B方归还曾抢夺的100斤土豆
C国收到的消息:
A国要求C方归还曾抢夺的20头牛
A国收到的消息:
B国要求A方归还曾抢夺的10只公鸡
C国收到的消息:
B国要求C方归还曾抢夺的15匹马
A国收到的消息:
C国要求A方曾抢夺的360斤小麦
B国收到的消息:
C国要求B方曾抢夺的50头驴
参考资料:
1.Java设计模式/耿祥义,张跃平著.——北京:清华大学出版社,2009.5