设计模式之中介者模式

**++++**阅读建议

嗨,伙计!刷到这篇文章咱们就是有缘人,在阅读这篇文章前我有一些建议:

  1. ++本篇文章大概5000多字,预计阅读时间长需要5分钟。++
  2. ++本篇文章的实战性、理论性较强,是一篇质量分数较高的技术干货文章,建议收藏起来,方便时常学习与回顾,温故而知新。++
  3. ++创作不易,免费的点赞、关注,请走上一走,算是对博主一些鼓励,让我更有动力输出更多的干货内容。++

什么是中介者模式

中介者模式是一种软件设计模式,它允许定义一个中间对象(中介者),来协调一组对象之间的交互。通过将一组对象之间的交互抽象化到一个单独的对象中,使得各个对象不必直接交互,而只与中介者发生交互,从而使原本复杂的多对多的关系变成相对简单的单对单或一对多的关系。

中介者模式有哪些核心角色

中介者模式(Mediator Pattern)包含以下四个核心角色:

  1. Mediator(抽象中介者):用来定义参与者与中介者之间的交互方式,如同事角色的注册、注销、消息的转发。
  2. ConcreteMediator(具体中介者):实现抽象中介者接口,实现具体交互方式。
  3. Colleague(抽象同事角色):抽象类或者接口,定义参与者如何进行交互,如发送消息、接收消息等。
  4. ConcreteColleague(具体同事角色):实现Colleague中的方法,定义具体行为。

中介者模式的目的是通过引入中介者来简化对象之间的复杂交互,将多对多的复杂关系转化为相对简单的一对多关系。中介者的职责是进行结构性中转作用和协调行为。结构性中转作用是指各个同事对象不再需要显式地引用其他同事,当需要和其他同事进行通信时,可通过中介者来实现间接调用。协调行为是指中介者可以更进一步地对同事之间的关系进行封装,同事可以一致地和中介者进行交互,而不需要指明中介者需要具体怎么做,中介者根据封装在自身内部的协调逻辑对同事的请求进行进一步处理。

java 复制代码
// 抽象中介者  
public abstract class Mediator {
    public abstract void register(Colleague colleague);
    public abstract void relay(Colleague cl); //转发
}
java 复制代码
public class ConcreteMediator extends Mediator {
    private List<Colleague> colleagues = new ArrayList<Colleague>();
    public void register(Colleague colleague) {
        if (!colleagues.contains(colleague)) {
            colleagues.add(colleague);
            colleague.setMedium(this);
        }
    }
    public void relay(Colleague cl) {
        for (Colleague ob : colleagues) {
            if (!ob.equals(cl)) {
                ((Colleague) ob).receive();
            }
        }
    }
}
java 复制代码
//抽象同事类
public abstract class Colleague {
    protected Mediator mediator;
    public void setMedium(Mediator mediator) {
        this.mediator = mediator;
    }
    public abstract void receive();
    public abstract void send();
}
java 复制代码
//具体同事类
public class ConcreteColleague1 extends Colleague {
    public void receive() {
        System.out.println("具体同事类1收到请求。");
    }
    public void send() {
        System.out.println("具体同事类1发出请求。");
        mediator.relay(this); //请中介者转发
    }
}
java 复制代码
//具体同事类
class ConcreteColleague2 extends Colleague {
    public void receive() {
        System.out.println("具体同事类2收到请求。");
    }
    public void send() {
        System.out.println("具体同事类2发出请求。");
        mediator.relay(this); //请中介者转发
    }
}
java 复制代码
public class MediatorPattern {
    public static void main(String[] args) {
        Mediator md = new ConcreteMediator();
        Colleague c1, c2;
        c1 = new ConcreteColleague1();
        c2 = new ConcreteColleague2();
        md.register(c1);
        md.register(c2);
        c1.send();
        System.out.println("-------------");
        c2.send();
    }
}

中介者模式如何实现

需求描述

通过上面的介绍,相信对中介者模式已经有了一个大概的印象了,这里再模拟一个业务场景来重点理解一下,中介者模式中各角色之间是如何交互的.

以前在农村的村部都会有一个大喇叭,上级有什么通知啥的、或者是谁家有个啥喜事都是通过个大喇叭通知给全体村民的,这里的大喇叭实际上就相当于一个中介者的角色,村长可以用来通知上级的重要指示,其他村民也可用来通知自己的喜事.如果使用中介者模式写一段程序来模拟这个过程,应该怎么实现呢?

实现方法

1、声明一个抽象的喇叭接口,即抽象中介者角色,定义两个抽象方法:注册喇叭的使用者、播放消息;

java 复制代码
/**
 * 抽象喇叭
 */
public interface Horn {
    /**
     * 注册使用者
     * @param villager
     */
    void register(Villager villager);

    /**
     * 播放消息
     * @param msg
     */
    void play(Villager villager,String msg);
}

2、声明一个具体的喇叭类,即具体的中介者角色,实现抽象喇叭接口,实现其中定义的抽象方法;

java 复制代码
/**
 * 具体的喇叭
 */
public class ConcreteHorn implements Horn{
    private List<Villager> list=new ArrayList<>();

    @Override
    public void register(Villager villager) {
        list.add(villager);
        villager.setHorn(this);
    }

    @Override
    public void play(Villager villager,String msg) {
        for (Villager obj : list) {
            if (!obj.equals(villager)) {
                obj.receive(msg);
            }
        }
    }
}

3、声明一个抽象的村民类,即抽象同事类,每一个村民都有权利使用喇叭,因此在抽象村民类内部定义一个喇叭属性,另外定义两个抽象方法:用于接受其他村民发的消息和自己向其他村民发消息;

java 复制代码
/**
 * 抽象村民
 */
public abstract class Villager {
    protected Horn horn;

    public void setHorn(Horn horn) {
        this.horn = horn;
    }

    /**
     * 发消息
     * @param msg
     */
    public abstract void send(String msg);

    /**
     * 收到消息
     * @param msg
     */
    public abstract void receive(String msg);
}

4、声明具体的村民类,即具体的同事类,这里声明两个作为村民代表,一个是村长类,另一个是村民代表张三类,继承抽象的村民类,并实现抽象村民类中的两个抽象方法;

java 复制代码
/**
 * 村长
 */
public class VillageHead extends Villager{
    @Override
    public void send(String msg) {
        this.horn.play(this,msg);
    }

    @Override
    public void receive(String msg) {
        System.out.println("村长收到消息:"+msg);
    }
}
java 复制代码
/**
 * 张三
 */
public class ZhangSan extends Villager{
    @Override
    public void send(String msg) {
        this.horn.play(this,msg);
    }

    @Override
    public void receive(String msg) {
        System.out.println("张三收到消息:"+msg);
    }
}
java 复制代码
/**
 * 其他村民
 */
public class OtherVillager extends Villager{
    @Override
    public void send(String msg) {
        this.horn.play(this,msg);
    }

    @Override
    public void receive(String msg) {
        System.out.println("其他村民收到消息:"+msg);
    }
}

5、编写客户端业务,模拟村长给村民发送上级通知、和张三给其他村民发布喜讯通知;

java 复制代码
public class Client {
    public static void main(String[] args) {
        Horn horn=new ConcreteHorn();
        Villager zhangsan=new ZhangSan();
        Villager otherVillager=new OtherVillager();
        Villager villageHead=new VillageHead();
        horn.register(zhangsan);
        horn.register(otherVillager);
        horn.register(villageHead);
        zhangsan.send("大家好,俺是村东头张三!俺娃考上县城第一中学了,晚上都到我家喝酒!");
        System.out.println("-------------");
        villageHead.send("各位村民注意了!上级调配的种子化肥已到村部,各家速来领取!");
    }
}

如何扩展

生活水平提高了,村里喇叭年久失修,也不太好用了,于是村民一致支持在村头广场上建个LED大屏,用途和以前的喇叭一样,也是用来方便传递消息,晚上还插放个新闻联播。怎么实现呢?很简单重新定义LED类,实现抽象喇叭接口,然后再调整一个客户端业务就可以了;这样村里就有两套传递消息的机制了,互不影响;

java 复制代码
public class LED implements Horn{
    private List<Villager> list=new ArrayList<>();
    @Override
    public void register(Villager villager) {
        this.list.add(villager);
        villager.setHorn(this);
    }

    @Override
    public void play(Villager villager, String msg) {
        for (Villager obj : list) {
            if (!obj.equals(villager)) {
                obj.receive(msg);
            }
        }
    }
}
java 复制代码
public class Client {
    public static void main(String[] args) {
        Villager zhangsan=new ZhangSan();
        Villager otherVillager=new OtherVillager();
        Villager villageHead=new VillageHead();
        Horn horn=new LED();
        horn.register(zhangsan);
        horn.register(otherVillager);
        horn.register(villageHead);
        villageHead.send("村民们注意了!村里新修的大屏今天正式投入使用了,晚上放电影,铁道游击队!");
    }
}

那么如果村里有新村民迁入了,应该怎么扩展,是不是也很简单了?

中介者模式适用哪些场景

中介者模式适用于具有以下特征的业务场景:

  • 多个对象之间存在着复杂的关联和交互关系,使得系统难以理解和维护;
  • 需要通过一个中间对象来封装多个对象之间的交互,以提高代码的可读性和可维护性;
  • 在系统中需要频繁地添加、删除或改变对象之间的交互关系,而中介者可以更好地管理和控制这些变化;
  • 需要在多个对象之间进行协调和通信,但是又不希望它们直接进行交互,以免产生复杂的耦合关系。

中介者模式的优点和缺点

中介者模式的优点在于:

  • 能够减少类之间的依赖关系,实现类之间的解耦;
  • 中介者可以统一管理类之间的交互规则,方便修改和扩展;
  • 当一组对象之间的交互很复杂的时候,中介者模式能够简化这些交互,使之变得清晰明了。
  • 中介者对象可能会变得非常复杂,因为它需要管理所有相关类的交互;
  • 中介者对象的变更可能会影响到所有的相关类,这可能会增加系统的风险;
  • 如果不恰当使用中介者模式,可能会导致系统的设计变得更加复杂。

然而,中介者模式也有一些缺点:

  • 中介者对象可能会变得非常复杂,因为它需要管理所有相关类的交互;
  • 中介者对象的变更可能会影响到所有的相关类,这可能会增加系统的风险;
  • 如果不恰当使用中介者模式,可能会导致系统的设计变得更加复杂。

总结

中介者模式是一种软件设计模式,它的目的是将一组对象之间的交互抽象化到一个单独的对象中,使得各个对象不必直接交互,而只与这个中间对象发生交互。这种模式可以帮助我们减少类之间的依赖关系,实现类之间的解耦,并简化复杂的交互关系。

++++

相关推荐
小江的记录本5 分钟前
【JVM虚拟机】JVM调优:常用JVM参数、调优核心指标、OOM排查、GC日志分析、Arthas工具使用(附《思维导图》+《面试高频考点清单》)
java·jvm·spring boot·后端·python·spring·面试
程序员cxuan16 分钟前
我花了两天时间,终于把 Codex 额度掉太快的问题整明白了!!
人工智能·后端·程序员
IT_陈寒17 分钟前
Vue这个动态响应坑把我整不会了
前端·人工智能·后端
金銀銅鐵18 分钟前
[Java] 用图形化界面演示 iadd, isub, iconst_<i> 指令的效果
java·后端·python
AskHarries30 分钟前
做国内还是出海
后端
J2虾虾35 分钟前
Spring AI Alibaba文档
java·人工智能·spring
YikNjy41 分钟前
break和continue
java·开发语言·算法
SomeOtherTime43 分钟前
Geojson相关(AI回答)
java·前端·python
日月云棠1 小时前
10 Integer —— 最常用的整数包装类深度解析
java·后端
大鸡腿同学1 小时前
大模型为何总 “胡说八道”?做完 RAG 知识库,我看懂了它的底层逻辑
后端