中介者模式
- 定义:定义一个封装一组如何交互的对象,通过使对象明确的相互引用来促进松散耦合,并允许独立地改变它们的交互
- 类型:行为型
- 适用场景:
- 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解
- 交互的公共行为,如果需要改变行为则可以增加新的中介者类
- 优点:
- 将一对多转化为一对一、降低程序复杂度
- 类之间解耦
- 缺点:
- 中介者过多,导致系统复杂
- 相关设计模式:
- 中介者模式和观察者模式:有时候会结合使用,用观察者模式来实现中介者模式角色间的通讯
coding
抽象同事类
/** * <p> * 抽象的同事类,也叫抽象组件,以前互相依赖的各个对象或组件,互 * 相之间以“同事” 称呼。主要定义一些各个具体同事类之间共有的方法。 * </p> * */ @Data @AllArgsConstructor @NoArgsConstructor public abstract class Colleague { /**聚合(弱关联)中介者对象*/ private Mediator mediator; private String name; public Colleague(String name,Mediator mediator){ this.name = name; this.mediator = mediator; } public void receiveMsg(String name,String message){ String sex = this instanceof BoyColleague ? "男" : "女"; System.out.println(String.format("%s同事%s收到来自%s的消息:%s",sex,getName(),name,message)); doReceiveMsg(name,message); } public abstract void doReceiveMsg(String name,String message); }
具体同事类
/** * <p> * 具体的同事类,Colleague 的具体实现类。 * 当一个同事类想要调用另一个同事的方法的时候,它必须调用中介者的方法, * 中介者中的方法再去调用其他同事的方法。 * 男同事 * </p> * */ public class BoyColleague extends Colleague { public BoyColleague(String name){ this.setName(name); } public BoyColleague(String name,Mediator mediator){ super(name,mediator); /**把自己的信息登记到hr那*/ getMediator().register(this); } /**发出约会信息*/ public void engagement (String content) { getMediator().contact(new BoyColleague(getName()),content); } @Override public void doReceiveMsg(String name ,String message) { /**do nothing*/ } } /** * <p> * 具体的同事类,Colleague 的具体实现类。 * 当一个同事类想要调用另一个同事的方法的时候,它必须调用中介者的方法, * 中介者中的方法再去调用其他同事的方法。 * 女同事 * </p> * */ public class GirlColleague extends Colleague { public GirlColleague(String name,Mediator mediator){ super(name,mediator); /**把自己的信息登记到hr那*/ getMediator().register(this); } public void agree(String name) { getMediator().contact(this,String.format( "%s,你好,我是%s,你就是我好找的人,我们去约会吧!",name,getName() )); } public void degree(String name){ getMediator().contact(this,String.format( "%s,你好,我是%s,我们俩不合适,抱歉!",name,getName() )); } @Override public void doReceiveMsg(String name , String message) { if (message.contains("高") || message.contains("富") || message.contains("帅")){ agree(name); }else{ degree(name); } System.out.println("==========================="); } }
抽象中介者
/** * <p>抽象中介者角色,主要定义一个接口,用于各个同事之间进行互相通信。与同事类相互依赖。</p> * */ public abstract class Mediator { Set<Colleague> colleagues; public void register(Colleague colleague){ if (colleagues == null){ colleagues = new HashSet<>(16); } this.colleagues.add(colleague); } public Set<Colleague> getColleagues(){ return this.colleagues; } public abstract void contact(Colleague colleague,String message); }
具体中介者
/** * <p>人事中介者,负者联络公司男女同事之间的情愫</p> * */ public class HrMediator extends Mediator{ @Override public void contact(Colleague colleague, String message) { this.getColleagues().forEach(col->{ if (colleague != col){ if (colleague instanceof BoyColleague && col instanceof GirlColleague){ /** 男同事发给女同事 */ col.receiveMsg(colleague.getName(),message); } if (colleague instanceof GirlColleague && col instanceof BoyColleague){ if (message.contains(col.getName())){ /** 女同事匹配男同事 */ col.receiveMsg(colleague.getName(),message); } } } }); } }
UML
测试
/** * <p>中介者测试</p> * */ public class MediatorTest { public static void main(String[] args) { HrMediator mediator = new HrMediator(); BoyColleague boy1 = new BoyColleague("张富贵",mediator); BoyColleague boy2 = new BoyColleague("李奋斗",mediator); BoyColleague boy3 = new BoyColleague("刘无能",mediator); GirlColleague girl = new GirlColleague("韩美丽",mediator); boy1.engagement("我就是高富帅,希望结交一位温柔贤惠的女士作为另一半!"); boy2.engagement("我很上进,工作很认真,我希望在这里找到我爱的人!"); boy3.engagement("话不多说,我喜欢女的,活的!"); } /** * 中介者模式很简单,就不多说了,也不在多举例子了, * 像服务注册与发现中心、现实中的房屋中介、婚介所等都是应用场景。 */ } ===========输出=========== 女同事韩美丽收到来自张富贵的消息:我就是高富帅,希望结交一位温柔贤惠的女士作为另一半! 男同事张富贵收到来自韩美丽的消息:张富贵,你好,我是韩美丽,你就是我好找的人,我们去约会吧! =========================== 女同事韩美丽收到来自李奋斗的消息:我很上进,工作很认真,我希望在这里找到我爱的人! 男同事李奋斗收到来自韩美丽的消息:李奋斗,你好,我是韩美丽,我们俩不合适,抱歉! =========================== 女同事韩美丽收到来自刘无能的消息:话不多说,我喜欢女的,活的! 男同事刘无能收到来自韩美丽的消息:刘无能,你好,我是韩美丽,我们俩不合适,抱歉! ===========================
源码中的应用
- java.util.Timer:会发现很多方法最后调用的都是sched()方法,可以看到sched()方法,Timer就相当于是个中介者,它去协调具体的TimerTask任务类,所有的任务都会到sched()方法,进行整体的协调
public class Timer { ... public void schedule(TimerTask task, Date time) { sched(task, time.getTime(), 0); } public void schedule(TimerTask task, Date firstTime, long period) { if (period <= 0) throw new IllegalArgumentException("Non-positive period."); sched(task, firstTime.getTime(), -period); } private void sched(TimerTask task, long time, long period) { ... } ... }