设计模式——中介者模式
中介者模式一般用于解决多个对象或者多个系统之间相互关联,交互的复杂关系的问题!这种关系一般是网状结构,使用中介者模式,将这种网状结构转换为星型结构,降低各个对象之间的耦合度。
网状结构一般会导致系统复杂,可扩展性差,对象可复用程度降低!
中介者模式的缺点是中介者类比较复杂,而且一旦出问题可能会影响整个系统!
中介者模式的核心是中介者与其同事之间的双向绑定关系,即中介者拥有需要交互的所有同事,同事拥有中介者的引用!
下面以实际生产中的一个架构模型,说明中介者的应用:
1、中介者的抽象
/* * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved */ package com.pt.mediator; /** * @description 中介者抽象,申明一个联络方法 * @author panteng * @date 17-2-22. */ public interface IMediator { /** * source和destination的类型设置为Object,实际上可以是中介者所有同事的抽象类 * 在这个接口里实际上可以不传递source 和 destination参数,根据消息内容判断来源的目的 * @param message */ void contact(String message); }
2、所有同事的抽象(核心是需要拥有对中介者的引用)
/* * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved */ package com.pt.mediator; /** * @description 所有同事的抽象类,每一个同事都应该持有对中介者的引用 * @author panteng * @date 17-2-22. */ public abstract class AbstractStation { String name; //站点名 IMediator mediator; //中介者 public AbstractStation(){ } public AbstractStation(String name, IMediator mediator){ this.name = name; this.mediator = mediator; } public IMediator getMediator(){ return mediator; } public void setMediator(IMediator mediator){ this.mediator = mediator; } }
3、同事类
/* * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved */ package com.pt.mediator; /** * @description 负责扫描待充值/查询的订单 * @author panteng * @date 17-2-22. */ public class AutoServer extends AbstractStation { public AutoServer(){ } public AutoServer(String name, IMediator mediator){ super(name, mediator); } void getMsg(String msg){ System.out.println("AutoServer接收消息:" + msg); if ("待充值订单".equals(msg)) { this.sendMsg("请求充值"); } } void sendMsg(String msg){ System.out.println("AutoServer发送消息:" + msg); this.mediator.contact(msg); } }
/* * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved */ package com.pt.mediator; /** * @description 负责业务处理 * @author panteng * @date 17-2-22. */ public class AppServer extends AbstractStation { public AppServer(){ } public AppServer(String name, IMediator mediator){ super(name, mediator); } void getMsg(String msg){ System.out.println("APPserver接收消息:" + msg); if ("请求充值".equals(msg)) { this.sendMsg("请发送至代理商"); } else if (msg.indexOf("充值结果") > -1) { this.sendMsg("修改订单状态,充值中"); } } void sendMsg(String msg){ this.mediator.contact(msg); } }
/* * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved */ package com.pt.mediator; /** * @description 负责数据层访问 * @author panteng * @date 17-2-22. */ public class DBPServer extends AbstractStation { public DBPServer(){ } public DBPServer(String name, IMediator mediator){ super(name, mediator); } void getMsg(String msg){ System.out.println("DBPserver接收消息:" + msg); if ("查询待充值订单".equals(msg)) { this.sendMsg("待充值订单"); } else if (msg.indexOf("修改订单状态") > -1) { System.out.println("DBP修改订单状态修改完毕"); } } void sendMsg(String msg){ System.out.println("DBPserver发送消息:" + msg); this.mediator.contact(msg); } }
/* * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved */ package com.pt.mediator; /** * @description 负责向代理商发送充值/查询请求 * @author panteng * @date 17-2-22. */ public class TomcatServer extends AbstractStation { public TomcatServer(){ } public TomcatServer(String name, IMediator mediator){ super(name, mediator); } void getMsg(String msg){ System.out.println("TomcatServer接收消息:" + msg); System.out.println("TomcatServer向代理商请求充值"); this.sendMsg("充值结果,充值成功... ..."); } void sendMsg(String msg){ this.mediator.contact(msg); } }
4、实际中介者
/* * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved */ package com.pt.mediator; /** * @description * @author panteng * @date 17-2-22. */ public class Mediator implements IMediator { AppServer appServer; AutoServer autoServer; DBPServer dbpServer; TomcatServer tomcatServer; public Mediator(){ } public Mediator(AppServer appServer, AutoServer autoServer, DBPServer dbpServer, TomcatServer tomcatServer){ this.appServer = appServer; this.autoServer = autoServer; this.dbpServer = dbpServer; this.tomcatServer = tomcatServer; this.appServer.setMediator(this); this.autoServer.setMediator(this); this.dbpServer.setMediator(this); this.tomcatServer.setMediator(this); } /** * source和destination的类型设置为Object,实际上可以是中介者所有同事的抽象类 * @param message */ public void contact(String message){ if (message.indexOf("增") > -1 || message.indexOf("删") > -1 || message.indexOf("改") > -1 || message.indexOf("查") > -1) { this.dbpServer.getMsg(message); return; } if (message.indexOf("待") > -1) { this.autoServer.getMsg(message); return; } if ("请求充值".equals(message) || message.indexOf("充值结果") > -1) { this.appServer.getMsg(message); } if ("请发送至代理商".equals(message)) { this.tomcatServer.getMsg(message); } } }
5、测试
/* * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved */ package com.pt.mediator; import org.junit.Test; /** * @description * @author panteng * @date 17-2-22. */ public class MediatorTest { @Test public void mediatorTest(){ AppServer appServer = new AppServer(); AutoServer autoServer = new AutoServer(); DBPServer dbpServer = new DBPServer(); TomcatServer tomcatServer = new TomcatServer(); IMediator mediator = new Mediator(appServer, autoServer, dbpServer, tomcatServer); autoServer.sendMsg("查询待充值订单"); } }
输出:
AutoServer发送消息:查询待充值订单
DBPserver接收消息:查询待充值订单
DBPserver发送消息:待充值订单
AutoServer接收消息:待充值订单
AutoServer发送消息:请求充值
APPserver接收消息:请求充值
TomcatServer接收消息:请发送至代理商
TomcatServer向代理商请求充值
APPserver接收消息:充值结果,充值成功... ...
DBPserver接收消息:修改订单状态,充值成功
DBP修改订单状态修改完毕
本例中,同事对象不需要关注其他同事对象,但这样可能会造成中介者的实现特别复杂!
实际应用中,对于发送消息的同事而言,知道其消息的接收者是谁,请求中介者时,需要将自己(消息的发送者)和目的同事(消息的接收者)传递给中介者,这样可方便中介者的实现,对外部逻辑影响并不大,因为消息发送者并不需要操作接受者的具体信息(如内部结构,方法等),只需要知道是谁即可。