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
- JAVA-设计模式之中介者模式
- java设计模式之中介者模式
- Java 设计模式之中介者模式
- Java 设计模式之中介者模式
- Java 设计模式之中介者模式
- java设计模式之中介者模式
- Java设计模式之中介者模式
- java设计模式之中介者模式
- java设计模式之中介者模式
- Java设计模式之中介者模式
- java设计模式之中介者模式
- JAVA设计模式之中介者模式
- Java设计模式之中介者模式
- Java设计模式之中介者模式
- Java 设计模式之中介者模式
- JAVA设计模式之中介者模式
- Java设计模式之中介者模式
- JAVA设计模式之中介模式
- 更改设置让Cheat Engine搜索数据
- Linux下的ip命令
- js蛋疼的Class(获取class对象)
- SpringMVC静态资源配置
- Ubuntukylin-17.10 安装virtualenv和virtualenvwrapper
- JAVA设计模式之中介者模式
- 个人信用良好贷款 买房却被拒!
- scala函数式编程第二章之函数(1)
- Problem6:ZigZag Conversion
- 左侧菜单切换后小图标跟随变化成选中的图标
- Python实现拉格朗日插值
- openlayers4 View fit:地图缩放问题
- 手把手带你实现Spring、Spring MVC与Mybatis整合工程的搭建
- C语言小程序,三子棋