本篇讲解Java设计模式中的中介模式,分为定义、模式应用前案例、结构、模式应用后案例、适用场景、模式可能存在的困惑和本质探讨7个部分。
定义
中介模式是用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
在新的分类方式中,中介模式模式被划分至类之间的交互类别中,其简化的是一组类之间复杂的交互关系。
模式应用前案例
现实生活中房屋中介用于连接众多买卖的双方,其实就是中介模式在现实中的应用,下面我们就拿这个案例来进行说明。先来看一下未使用中介模式前的代码实现。
public class Buyer {//买家private final String name;public Buyer(String name) {this.name = name; }public void sendMessage(Seller seller, String message) { System.out.println(this.name + \" sends a message: \" + message+ \" to \" + seller.getName()); }public String getName() {return this.name; }}public class Seller {//卖家private final String name;public Seller(String name) {this.name = name; }public void sendMessage(Buyer buyer, String message) { System.out.println(this.name + \" sends a message: \" + message + \" to \" + buyer.getName()); }public String getName() {return this.name; }}public class Client {//调用者代码public static void main(String[] args) {// 创建两个卖家对象 Seller seller1 = new Seller(\"Seller A\"); Seller seller2 = new Seller(\"Seller B\");//创建两个买家对象 Buyer buyer1 = new Buyer(\"Buyer A\"); Buyer buyer2 = new Buyer(\"Buyer B\");// 直接让卖家之间进行通信 seller1.sendMessage(buyer1, \"Hello, are you interested in collaborating?\"); seller2.sendMessage(buyer2, \"Yes, I am open to collaboration opportunities.\");// 其他逻辑... }}
从上述代码来看,最主要的问题就是买家类和卖家类直接发生耦合,后续维护非常困难。
结构
中介模式的示例代码实现如下。
public abstract class Colleague {protected Mediator mediator;public Colleague(Mediator mediator){this.mediator = mediator; }public abstract void send(String message);public abstract void receive(String message);}public class ConcreteColleague1 extends Colleague{public ConcreteColleague1(Mediator mediator) {super(mediator); }@Overridepublic void send(String message) { System.out.println(\"Colleague 1 sends: \" + message); mediator.send(message, this); }@Overridepublic void receive(String message) { System.out.println(\"Colleague 1 receives: \" + message); }}public class ConcreteColleague2 extends Colleague{public ConcreteColleague2(Mediator mediator) {super(mediator); }@Overridepublic void send(String message) { System.out.println(\"Colleague 2 sends: \" + message); mediator.send(message, this); }@Overridepublic void receive(String message) { System.out.println(\"Colleague 2 receives: \" + message); }}public abstract class Mediator {public abstract void send(String message, Colleague colleague);}public class ConcreteMediator extends Mediator{private ConcreteColleague1 colleague1;private ConcreteColleague2 colleague2;public void setColleague1(Colleague colleague1) {this.colleague1 = (ConcreteColleague1) colleague1; }public void setColleague2(Colleague colleague2) {this.colleague2 = (ConcreteColleague2) colleague2; }@Overridepublic void send(String message, Colleague colleague) {if (colleague == colleague1) { colleague2.receive(\"Message from 1 to 2\"); } else if (colleague == colleague2) { colleague1.receive(\"Message from 2 to 1\"); } }}public class Client {public static void main(String[] args) { ConcreteMediator mediator = new ConcreteMediator(); Colleague colleague1 = new ConcreteColleague1(mediator); Colleague colleague2 = new ConcreteColleague2(mediator); mediator.setColleague1(colleague1); mediator.setColleague2(colleague2); colleague1.send(\"Hello from A\"); colleague2.send(\"Hello from B\"); }}
从中介模式的结构来看,原来Colleague的各个实现类之间需要直接交互,现在交互逻辑统一移到Mediator实现类中实现,从而Colleague各个实现类之间可以实现松耦合。
模式应用后案例
上面房屋中介的案例,在使用中介模式之后的代码实现如下。
买家和卖家的家族类如下。
public interface IPerson {// 买家卖家接口String getName();void sendMessage(String message);void receiveMessage(String message);}public class Buyer implements IPerson{//具体买家类private final String name;private final IEstateMediator mediator;public Buyer(IEstateMediator mediator, String name){this.mediator=mediator;this.name=name; mediator.registerPerson(this); }@Overridepublic String getName(){return this.name;}@Overridepublic void sendMessage(String msg){//System.out.print(this.name +\" sends a message: \"+msg+\"\\n\");this.mediator.sendMessage(msg,this); }@Overridepublic void receiveMessage(String msg){ System.out.print(this.name +\" receives a messages:\"+msg+\"\\n\"); }}public class Seller implements IPerson {// 具体卖家类private final String name;private final IEstateMediator mediator;public Seller(IEstateMediator mediator, String name){this.mediator=mediator;this.name=name; mediator.registerPerson(this); }@Overridepublic String getName(){return this.name;}@Overridepublic void sendMessage(String msg){//System.out.print(this.name +\" sends a message: \"+msg+\"\\n\");this.mediator.sendMessage(msg,this); }@Overridepublic void receiveMessage(String msg){ System.out.print(this.name +\" receives a messages:\"+msg+\"\\n\"); }}
房屋中介的家族类如下。
public interface IEstateMediator {//中介者接口void registerPerson(IPerson person);void sendMessage(String message, IPerson person);}public class RealEstateMediator implements IEstateMediator {public List getSellers() {return this.sellers; }public List getBuyers() {return this.buyers; }private final List sellers = new ArrayList();private final List buyers = new ArrayList();@Overridepublic void registerPerson(IPerson person) {if(person instanceof Seller) {this.sellers.add(person); }else if(person instanceof Buyer) {this.buyers.add(person); } }@Overridepublic void sendMessage(String message, IPerson person) {// 具体中介者类if(person instanceof Seller) {//说明是卖家发给买家for(IPerson buyer : this.buyers) {// 处理从卖家发出的消息,并转发给其他买家 System.out.println(person.getName() + \" sends message: \" + message +\" to \" + buyer.getName()); buyer.receiveMessage(message); } }else if(person instanceof Buyer) {//说明是买家发给卖家for(IPerson seller : this.sellers) {// 处理从买家发出的消息,并转发给其他卖家 System.out.println(person.getName() + \" sends message: \" + message +\" to \" + seller.getName()); seller.receiveMessage(message); } } }}
最后,调用方代码实现如下。
public class Client {//调用方代码public static void main(String[] args) {// 创建房地产中介对象 IEstateMediator mediator = new RealEstateMediator();// 创建两个卖家对象,并注册到房地产中介 IPerson seller1 = new Seller(mediator, \"Seller A\"); IPerson seller2 = new Seller(mediator, \"Seller B\");// 创建两个买家对象,并注册到房地产中介 IPerson buyer1 = new Buyer(mediator, \"Buyer A\"); IPerson buyer2 = new Buyer(mediator, \"Buyer B\");// 卖家发送消息给其他买家 seller1.sendMessage(\"Hello, I am a seller, are you interested in collaborating?\"); seller2.sendMessage(\"Yes, I am a seller, I am open to collaboration opportunities.\");// 买家发送消息给其他卖家 buyer1.sendMessage(\"Hello, I am a buyer, are you interested in collaborating?\"); buyer2.sendMessage(\"Yes, I am a buyer, I am open to collaboration opportunities.\");// 其他逻辑... }}
从最终的调用方代码来看,买家和卖家在发送消息时,都不需要再关注具体的卖家或买家,两者之间实现松耦合。买家和卖家之间关系的逻辑都放在房屋中介类中实现。
适用场景
中介者模式适用于以下场景:
1)一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解
2)一个对象引用其它很多对象并且直接与这些对象通信,导致难以复用该对象。
3)需要通过一个中心化的调度器来协调多个对象之间的交互,并减少对象直接通信带来的复杂性时
4)希望能够降低系统内各个组件之间依赖关系、提高系统灵活性和可维护性时,可以使用中介者模式
5)一些具有交互逻辑但不应该彼此直接知道对方存在的类
模式可能存在的困惑
困惑1:在中介者结构中,中介Mediator家族类被定性为核心类。我们知道Mediator及实现类中只是负责管理关系,似乎核心业务逻辑还是在Colleage实现类中,如何解释?
现实世界中很多场景下,实际上关系本身可能要比产生关系的具体系统要更有价值。比如,对于房屋中介,能尽快促成交易的前提是必须维护很多买家和卖家,并通过大数据分析,找到可能潜在会发生交易的买家和卖家之间的关系,这种关系的发现本身是很有价值的。因此,中介家族类归属于核心类别中。
本质
在面向对象的很多场景应用中,我们会尽量简化众多交互者之间的关系,比如通过减少交互数量或者将交互确定性等手段。
然而,现实中也有一些场景,众多交互者之间确实有交互的需求,并且这种交互具有不确定性。
中介者模式的本质在于通过管理关系的复杂性获得价值,从而使发生关系的众多参与方解耦。