对于那些存在对象之间复杂交互关系的系统,中介者模式提供了一种简化复杂交互的解决方案,即经过引入一个中介者,将本来对象之间的两两交互转化为每一个对象与中介者之间的交互java
以微信聊天为例,能够用户与用户直接聊天,也能够经过微信群聊天。前者的话,用户要和别的用户加为好友,即用户和用户之间存在多对多关系,一个用户若是要将相同的信息发送给全部其余用户,必须一个一个发送。而若是使用群聊天,一个用户能够向多个用户发送相同信息而无须一一进行发送,只需将信息发送到群中便可,群的做用就是将发送者所发送的信息转发给每个接收者用户。微信
在用户与用户直接聊天的设计方案中,用户对象之间存在很强关联性,将致使系统出现以下问题:app
根据单一职责原则,咱们应尽可能将对象细化,使其只负责单一职责。一个由不少对象构成的模块,为了减小对象两两之间复杂的引用关系,咱们须要使用中介者模式,这就是中介者模式的模式动机。ide
用一个中介对象来封装一系列对象交互,中介者使各对象不需显式地相互引用,从而使其耦合松散,并且能够独立改变它们之间的交互。中介者模式又称调停者模式,它是一种对象行为型模式。测试
Mediator(抽象中介者)this
定义一个接口,该接口应用于各同事对象之间的通讯设计
ConcreteMediator(具体中介者)code
抽象中介类的子类,经过协调各个同事对象来实现协做行为,了解并维护它对各个同事对象的引用。对象
Colleague(抽象同事类)blog
定义各同事的公有方法
ConcreteColleague(具体同事类)
每个同事对象都引用一个中介者对象,每个同事对象在须要时和其余同事对象通讯时,先与中介者通讯,经过中介者来间接完成与其余同事的通讯
经过引入中介者对象,能够将系统的网状结构变成以中介者为中心的星状结构。在这个形状结构中,同事对象再也不直接与另外一个对象联系,它经过中介者对象与另外一个对象发生相互做用。
若是对象之间存在多对多的相互关系,能够将对象之间的一些交互行为从各个对象中分离出来,并集中封装在一个中介者对象中,并由该中介者进行通讯和协调,这样对象间的多对多的复杂关系就能够经过简单的多对一关系实现,符合迪米特法则,即“只与你直接的朋友们通讯,并且只要可能,朋友数目越少越好”。
中介者承担了如下两方面的职责:
某论坛会员经过聊天室进行信息交流,普通会员(CommonMember)能够给其余会员发送文本信息,钻石会员(DiamondMember)既能够给其余会员发送文本信息,还能够发送图片信息。聊天室能够对不雅字符进行过滤,能够对发送图片的大小进行控制。
抽象中介者类 AbstractChatroom(抽象聊天室类)
public abstract class AbstractChatroom { // 注册同事对象的方法 public abstract void register(Member member); // 同事之间发送文本信息方法 public abstract void sendText(String from, String to, String message); // 同事之间发送图片信息 public abstract void sendImage(String from, String to, String image); }
抽象同事类 Member(抽象会员类)
public abstract class Member { // 维持一个抽象中介者的引用,用于调用中介者的方法 protected AbstractChatroom chatroom; protected String name; public Member(String name) { this.name = name; } public AbstractChatroom getChatroom() { return chatroom; } public void setChatroom(AbstractChatroom chatroom) { this.chatroom = chatroom; } public String getName() { return name; } public void setName(String name) { this.name = name; } // 因为不一样类型会员发送文本信息和图片信息的方式不一样 // 所以对这两个方法进行抽象声明 public abstract void sendText(String to, String message); public abstract void sendImage(String to, String image); public void receiveText(String from, String message) { System.out.println(from + "发送文本给" + this.name + ",内容为:" + message); } public void receiveImage(String from, String image) { System.out.println(from + "发送图片给" + this.name + ",内容为:" + image); } }
具体中介者类 ChatGroup(具体聊天室类)
import java.util.Hashtable; public class ChatGroup extends AbstractChatroom { // 定义一个集合对象存储须要发生交互的同事对象 private Hashtable<String, Member> members = new Hashtable<String, Member>(); // 提供注册方式,将同事对象加入集合中 @Override public void register(Member member) { if (!members.contains(member)) { members.put(member.getName(), member); member.setChatroom(this); } } @Override public void sendText(String from, String to, String message) { Member member = members.get(to); String newMessage = message; // 模拟不雅字符过滤 newMessage = message.replace("日", "*"); // 调用会员接收方法 member.receiveText(from, newMessage); } @Override public void sendImage(String from, String to, String image) { Member member = members.get(to); // 模拟图片大小判断 if (image.length() > 5) { System.out.println("图片太大,发送失败"); } else { // 调用会员接收方法 member.receiveImage(from, image); } } }
具体同事类 CommonMember(普通会员类)
public class CommonMember extends Member { public CommonMember(String name) { super(name); } @Override public void sendText(String to, String message) { System.out.println("普通会员发送信息:"); chatroom.sendText(name, to, message); } @Override public void sendImage(String to, String image) { System.out.println("普通会员不能发送图片!"); } }
具体同事类 DiamondMember(钻石会员类)
public class DiamondMember extends Member { public DiamondMember(String name) { super(name); } @Override public void sendText(String to, String message) { System.out.println("钻石会员发送信息:"); chatroom.sendText(name, to, message); } @Override public void sendImage(String to, String image) { System.out.println("钻石会员发送图片"); chatroom.sendImage(name, to, image); } }
客户端测试类 Client
public class Client { public static void main(String[] args) { AbstractChatroom happyChat = new ChatGroup(); Member member1, member2, member3, member4, member5; member1 = new DiamondMember("张三"); member2 = new DiamondMember("李四"); member3 = new CommonMember("王五"); member4 = new CommonMember("小芳"); member5 = new CommonMember("小红"); happyChat.register(member1); happyChat.register(member2); happyChat.register(member3); happyChat.register(member4); happyChat.register(member5); member1.sendText("李四", "李四,你好"); member2.sendText("张三", "张三,你好"); member1.sendText("李四", "今每天气不错,有日"); member2.sendImage("张三", "一个很大很大的太阳"); member2.sendImage("张三", "太阳"); member3.sendText("小芳", "还有问题吗?"); member3.sendText("小红", "还有问题吗?"); member4.sendText("王五", "没有了,谢谢"); member5.sendText("王五", "我也没有了"); member5.sendImage("王五", "谢谢"); } }
运行结果
若是须要增长新的具体中介类,只需继承抽象中介者类并实现其中方法便可,新的具体中介者类能够对信息进行不一样的处理,客户端只需修改少许代码(若是使用配置文件的话能够不修改代码)
若是增长新的同事类,继承抽象同事类并实现便可,同事类之间无直接引用关系。本实例中,中介者对同事类的引用创建在抽象层,所以在客户端实例化新增的同事类便可直接使用该对象
中介者模式优势:
中介者模式缺点:
如下状况可使用中介者模式: