JAVA设计模式之中介者模式

来源:互联网 发布:数组在内存中如何存储 编辑:程序博客网 时间:2024/05/17 01:04

1. 什么是中介者模式?

中介者模式(Mediator Pattern)是用一个中介对象(中介者)来封装一系列对象之间的交互,中介者使各对象之间不用显式的相互引用,从而使其耦合松散,而且可以独立的改变他们之间的交互。中介者模式又称为调停者模式,是一种对象行为型模式。


如果系统之中出现大量对象之间相互引用,将会造成

(1)系统结构变得复杂。对象与对象之间存在大量相互引用,若一个对象改变,与之关联的对象都可能要做出相应的改变。

(2)系统可扩展性降低。增加一个对象,就要去其他相关对象上面增加此对象的引用。增加了对象之间的耦合性。

(3)对象复用性降低。一个对象存在很多其他对象的引用,导致此对象不易于复用于其他场景。

 

图片源于网络

 

图中A对象中就有BCDHG对象的引用,A对象和这几个对象是直接耦合的,不易于扩展与维护。采用中介者模式后,所有对象都只和中介者(Mediator)打交道,所有的调用关系都是中介者来维护的。此时此刻A对象解脱了,假如A有份报告要交给BCD,他不用自己亲自给每个对象送去了,只需要交给Mediator转发给BCD就可以了。


但是一定要注意,因为中介者中维护了几乎所有对象的引用和调用行为,中介者会变得异常复杂和庞大。所以遇到大量对象相互引用的时候一定要权衡利弊,设计是否合理,不是说只要使用模式一定就是最好的。

2. 角色

 

图片源于网络

抽象中介者(Mediator):中介者抽象类。提供了一个同事对象联络的抽象方法。可以是接口或抽象类。


具体中介者(ConcreteMediator):实现抽象中介者类的抽象方法。具体中介者需要知道所有具体同事类,并且将一个具体同事类的信息传递给另一个具体同事类。


抽象同事(Colleague):定义所有具体同事的共同方法。可以是接口或抽象类。


具体同事(ConcreteColleague):实现抽象同事类的抽象方法。内部有一个中介者的引用。


3. 优点

(1)将系统对象与对象直接的调用关系分离出来进行单独封装,同事对象(Colleague)内没有显式的的调用其他同事对象,使耦合松散。

(2)同事对象(Colleague)抽离了对其他对象的引用,使得同事对象可以重用于不同的场景,不用单独扩展,可以使同事对象的数量减少。

4. 缺点

当使用中介者模式将对象与对象之间的调用关系分离出来后,中介者内部必须要知道每一个对象类和他们之间的调用关系,这会造成中介者代码复杂且庞大,很不容易维护。


如果有4个同事对象需要相互联系,则中介者对象中就会存在4*3=12种不同的相互调用方法,同事对象越多,中介者越复杂庞大。因此个人觉得,如果将接收者和发送者交给客户端来注册,不完全交给中间者管理,中介者对象只需要维护已经注册了的发送者和接收者,以及他们之间相互调用的公共方法,中介者会相对较好维护。如6例。

5. 使用场景

(1)系统对象之间存在复杂的引用关系,系统结构混乱难以理解。

(2)一个对象直接引用了其他对象,且直接和他们进行通信,造成这个对象难以复用与其他场景。

(3)想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的具体中介者类。


个人理解:其实这个就是造成中介者代码复杂庞大的原因,因为为了不生成太多的子类,中介者就需要维护所有的交互行为,4个对象就有12种交互行为,6个对象就有30种交互行为,因此示例代码中所举例子,采用一种折中的办法,中介者不维护所有的交互关系和交互对象,只维护抽象发送者、抽象接收者和公共调用关系,而实际的发送者和接收者交给客户端进行注册。

6. 示例代码

每种事物都具有两面性,此例子虽然解决了中介者类复杂庞大不好维护的缺点,但是却不能实现接收者与接收者对话,如B、C、D之间的对话。想要B、C、D之间相互对话必须重新注册接收者和发送者。

(1)抽象中介者

/** * 抽象中介者类 */public interface IMediator {/** * 中介者给同事双方相互联系的方法* @param person   发送请求的同事类* @param message  发送的消息 */public void contact(String message,AbstractPerson person);}

(2)具体中介者

/** * 具体的中介者对象 */public class ConcreteMediator implements IMediator {// 接收者(list列表可以实现一个发送者和多个接收者对话,一对多关系)private List<AbstractPerson> receivers = new ArrayList<AbstractPerson>();// 发送者private AbstractPerson sender;/** * 注册接收者 * @param persons */public void setReceiver(AbstractPerson... persons) {if (persons != null && persons.length > 0)for (AbstractPerson person : persons) {receivers.add(person);}}/** * 删除接收者 * @param receiver */public void removeReceiver(AbstractPerson...RECEIVERS) {if (RECEIVERS != null && RECEIVERS.length > 0)for(AbstractPerson receiver:RECEIVERS)receivers.remove(receiver);}/** * 注册发送者 * @param persen */public void setSender(AbstractPerson persen) {this.sender = persen;}@Overridepublic void contact(String message, AbstractPerson person) {if (person == sender) {for (AbstractPerson receiver : receivers)receiver.handleMessage(message);} else {sender.handleMessage(message);}}}


(3)抽象同事

/** *公共抽象同事类 *由于有重复的属性和方法,此处采用abstract类 */public abstract class AbstractPerson {protected IMediator mediator;protected String personName;public AbstractPerson(String personName,IMediator mediator) {this.personName=personName;this.mediator=mediator;}/** * 同事之间联系的方法* @param message  发送的消息 */public void contact(String message){if(message!=null && !"".equals(message))mediator.contact(message,this);}/** * 此对象处理消息的方法* @param message  接收到的消息 */public abstract void handleMessage(String message);}

(4)具体同事

/** * 具体同事A */public class PersonA extends AbstractPerson {public PersonA(String personName,IMediator mediator) {super(personName, mediator);}@Overridepublic void handleMessage(String message) {if(message!=null && !"".equals(message))System.out.println(personName+" 收到消息:"+message);}}/** * 具体同事B */public class PersonB extends AbstractPerson{public PersonB(String personName,IMediator mediator) {super(personName, mediator);}@Overridepublic void handleMessage(String message) {if(message!=null && !"".equals(message))System.out.println(personName+" 收到消息:"+message);}}/** * 具体同事C */public class PersonC extends AbstractPerson {public PersonC(String personName,IMediator mediator) {super(personName, mediator);}@Overridepublic void handleMessage(String message) {if(message!=null && !"".equals(message))System.out.println(personName+" 收到消息:"+message);}}/** * 具体同事D */public class PersonD extends AbstractPerson {public PersonD(String personName,IMediator mediator) {super(personName, mediator);}@Overridepublic void handleMessage(String message) {if(message!=null && !"".equals(message))System.out.println(personName+" 收到消息:"+message);}}

 

(5)测试

public class Client {public static void main(String[] args) {//new一个中介者ConcreteMediator mediator=new ConcreteMediator();//new一个发送者AAbstractPerson personA=new PersonA("A君", mediator);//new一个接收者BAbstractPerson personB=new PersonB("B君", mediator);//注册发送者mediator.setSender(personA);//注册接收者mediator.setReceiver(personB);System.out.println("A对B说:");personA.contact("B君,你吃早饭没有?");System.out.println("-----------");//再new 多个接收者AbstractPerson personC=new PersonC("C君", mediator);AbstractPerson personD=new PersonD("D君", mediator);mediator.setReceiver(personC,personD);System.out.println("A对BCD说:");personA.contact("你们今天编程了吗?");System.out.println("-----------");System.out.println("DBC分别回答A:");personD.contact("A君,别装逼!");personB.contact("呵呵");personC.contact("今天天气不错!");System.out.println("-----------");//清除B和C接收者mediator.removeReceiver(personB,personC);System.out.println("A单独对D说:");personA.contact("D君,别BB!");}}

(6)测试结果

A对B说:B君 收到消息:B君,你吃早饭没有?-----------A对BCD说:B君 收到消息:你们今天编程了吗?C君 收到消息:你们今天编程了吗?D君 收到消息:你们今天编程了吗?-----------DBC分别回答A:A君 收到消息:A君,别装逼!A君 收到消息:呵呵A君 收到消息:今天天气不错!-----------A单独对D说:D君 收到消息:D君,别BB!

注意:文中自我理解部分属于自己的对中介者模式的一种理解,不能说全对,若不对请批评指正!

【四川乐山程序员联盟,欢迎大家加群相互交流学习5 7 1 8 1 4 7 4 3】

参考文章http://www.cnblogs.com/chenssy/p/3348520.html