一文彻底搞明白中介模式

开发 前端
在面向对象的很多场景应用中,我们会尽量简化众多交互者之间的关系,比如通过减少交互数量或者将交互确定性等手段。

本篇讲解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);
    }

@Override
public void send(String message) {
        System.out.println("Colleague 1 sends: " + message);
        mediator.send(message, this);
    }

@Override
public void receive(String message) {
        System.out.println("Colleague 1 receives: " + message);
    }
}

public class ConcreteColleague2 extends Colleague{
public ConcreteColleague2(Mediator mediator) {
super(mediator);
    }

@Override
public void send(String message) {
        System.out.println("Colleague 2 sends: " + message);
        mediator.send(message, this);
    }

@Override
public 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;
    }

@Override
public 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);
    }

@Override
public String getName(){
return this.name;}

@Override
public void sendMessage(String msg){
//System.out.print(this.name +" sends a message: "+msg+"\n");
this.mediator.sendMessage(msg,this);
    }

@Override
public 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);
    }

@Override
public String getName(){
return this.name;}

@Override
public void sendMessage(String msg){
//System.out.print(this.name +" sends a message: "+msg+"\n");
this.mediator.sendMessage(msg,this);
    }

@Override
public 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<IPerson> getSellers() {
return this.sellers;
    }

public List<IPerson> getBuyers() {
return this.buyers;
    }

private final List<IPerson> sellers = new ArrayList<>();

private final List<IPerson> buyers = new ArrayList<>();

@Override
public void registerPerson(IPerson person) {

if(person instanceof Seller) {
this.sellers.add(person);
        }else if(person instanceof Buyer) {
this.buyers.add(person);
        }
    }

@Override
public 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实现类中,如何解释?

现实世界中很多场景下,实际上关系本身可能要比产生关系的具体系统要更有价值。比如,对于房屋中介,能尽快促成交易的前提是必须维护很多买家和卖家,并通过大数据分析,找到可能潜在会发生交易的买家和卖家之间的关系,这种关系的发现本身是很有价值的。因此,中介家族类归属于核心类别中。

本质

在面向对象的很多场景应用中,我们会尽量简化众多交互者之间的关系,比如通过减少交互数量或者将交互确定性等手段。

然而,现实中也有一些场景,众多交互者之间确实有交互的需求,并且这种交互具有不确定性。

中介者模式的本质在于通过管理关系的复杂性获得价值,从而使发生关系的众多参与方解耦。

责任编辑:武晓燕 来源: 今日头条
相关推荐

2024-05-09 09:09:19

组合模式对象

2024-05-10 08:43:04

外观模式接口系统

2024-05-11 14:18:44

迭代器模式业务

2024-05-17 10:08:59

享元模式分类方式

2024-05-15 17:41:37

备忘录模式多线程

2019-08-27 14:46:59

ElasticSearES数据库

2020-07-10 08:03:35

DNS网络ARPAne

2023-05-29 08:45:45

Java注解数据形式

2023-03-13 08:12:37

Golang编程路径问题

2019-09-09 11:02:17

Nginx进程模型

2021-05-06 08:03:07

IPIP网络模式calicok8s

2023-11-06 09:06:54

分布式一致性数据

2019-10-28 10:19:27

JVM 类加载器Java

2020-03-18 14:00:47

MySQL分区数据库

2021-06-30 08:45:02

内存管理面试

2022-06-07 10:13:22

前端沙箱对象

2023-10-27 08:15:45

2022-05-30 10:37:35

分布式事务反向补偿

2020-12-07 06:19:50

监控前端用户

2021-07-08 10:08:03

DvaJS前端Dva
点赞
收藏

51CTO技术栈公众号