瑞_23种设计模式_中介者模式

文章目录

    • 1 中介者模式(Mediator Pattern)
      • 1.1 介绍
      • 1.2 概述
      • 1.3 中介者模式的结构
      • 1.4 中介者模式的优缺点
      • 1.5 中介者模式的使用场景
    • 2 案例一
      • 2.1 需求
      • 2.2 代码实现
    • 3 案例二
      • 3.1 需求
      • 3.2 代码实现

🙊 前言:本文章为瑞_系列专栏之《23种设计模式》的中介者模式篇。本文中的部分图和概念等资料,来源于博主学习设计模式的相关网站《菜鸟教程 | 设计模式》和《黑马程序员Java设计模式详解》,特此注明。本文中涉及到的软件设计模式的概念、背景、优点、分类、以及UML图的基本知识和设计模式的6大法则等知识,建议阅读 《瑞_23种设计模式_概述》

本系列 - 设计模式 - 链接:《瑞_23种设计模式_概述》

⬇️本系列 - 创建型模式 - 链接🔗

  单例模式:《瑞_23种设计模式_单例模式》
  工厂模式:《瑞_23种设计模式_工厂模式》
  原型模式:《瑞_23种设计模式_原型模式》
抽象工厂模式:《瑞_23种设计模式_抽象工厂模式》
 建造者模式:《瑞_23种设计模式_建造者模式》

⬇️本系列 - 结构型模式 - 链接🔗

  代理模式:《瑞_23种设计模式_代理模式》
 适配器模式:《瑞_23种设计模式_适配器模式》
 装饰者模式:《瑞_23种设计模式_装饰者模式》
  桥接模式:《瑞_23种设计模式_桥接模式》
  外观模式:《瑞_23种设计模式_外观模式》
  组合模式:《瑞_23种设计模式_组合模式》
  享元模式:《瑞_23种设计模式_享元模式》

⬇️本系列 - 行为型模式 - 链接🔗

模板方法模式:《瑞_23种设计模式_模板方法模式》
  策略模式:《瑞_23种设计模式_策略模式》
  命令模式:《瑞_23种设计模式_命令模式》
 职责链模式:《瑞_23种设计模式_职责链模式》
  状态模式:《瑞_23种设计模式_状态模式》
 观察者模式:《瑞_23种设计模式_观察者模式》
 中介者模式:《后续更新》
 迭代器模式:《后续更新》
 访问者模式:《后续更新》
 备忘录模式:《后续更新》
 解释器模式:《后续更新》

在这里插入图片描述

1 中介者模式(Mediator Pattern)

瑞:中介者模式在框架设计中经常使用,即使框架内部再复杂,其使用方法也会相对简单。如Spring框架中的 BeanFactory 就是中介者模式的一个实现,它作为中介者,负责管理和创建应用程序中的所有 beans ,而不是让 beans 直接相互引用或创建。

  中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。

  瑞:行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。
  瑞:行为型模式分为类行为模式对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性

中介者模式属于:对象行为模式

1.1 介绍

  • 意图:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

  • 主要解决:对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,同时若一个对象发生改变,我们也需要跟踪与之相关联的对象,同时做出相应的处理。

  • 何时使用:多个类相互耦合,形成了网状结构。

  • 如何解决:将上述网状结构分离为星型结构。

  • 关键代码:对象 Colleague 之间的通信封装到一个类中单独处理。

  • 应用实例
      1️⃣ 中国加入 WTO 之前是各个国家相互贸易,结构复杂,现在是各个国家通过 WTO 来互相贸易。
      2️⃣ 机场调度系统。
      3️⃣ MVC 框架,其中C(控制器)就是 M(模型)和 V(视图)的中介者。

  • 优点
      1️⃣ 降低了类的复杂度,将一对多转化成了一对一。
      2️⃣ 各个类之间的解耦。
      3️⃣ 符合迪米特原则。

  • 缺点
      1️⃣ 中介者会庞大,变得复杂难以维护。

  • 使用场景
      1️⃣ 系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象。
      2️⃣ 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。

  • 注意事项
      1️⃣ 不应当在职责混乱的时候使用

1.2 概述

定义:中介者模式又叫调停模式,定义一个中介角色来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。

  一般来说,同事类之间的关系是比较复杂的,多个同事类之间互相关联时,他们之间的关系会呈现为复杂的网状结构,这是一种过度耦合的架构,即不利于类的复用,也不稳定。例如在下左图中,有六个同事类对象,假如对象1发生变化,那么将会有4个对象受到影响。如果对象2发生变化,那么将会有5个对象受到影响。也就是说,同事类之间直接关联的设计是不好的。

  如果引入中介者模式,那么同事类之间的关系将变为星型结构,从下图中可以看到,任何一个类的变动,只会影响的类本身,以及中介者,这样就减小了系统的耦合。一个好的设计,必定不会把所有的对象关系处理逻辑封装在本类中,而是使用一个专门的类来管理那些不属于自己的行为。

在这里插入图片描述

1.3 中介者模式的结构

  • 中介者模式主要包含以下角色:
      1️⃣ Subject:抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
      2️⃣ 具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
      3️⃣ 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
      4️⃣ 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。

1.4 中介者模式的优缺点

优点

  • 松散耦合
      中介者模式通过把多个同事对象之间的交互封装到中介者对象里面,从而使得同事对象之间松散耦合,基本上可以做到互补依赖。这样一来,同事对象就可以独立地变化和复用,而不再像以前那样“牵一处而动全身”了。

  • 集中控制交互
      多个同事对象的交互,被封装在中介者对象里面集中管理,使得这些交互行为发生变化的时候,只需要修改中介者对象就可以了,当然如果是已经做好的系统,那么就扩展中介者对象,而各个同事类不需要做修改。

  • 一对多关联转变为一对一的关联
      没有使用中介者模式的时候,同事对象之间的关系通常是一对多的,引入中介者对象以后,中介者对象和同事对象的关系通常变成双向的一对一,这会让对象的关系更容易理解和实现。

缺点

  • 当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护。

1.5 中介者模式的使用场景

  • 系统中对象之间存在复杂的引用关系,系统结构混乱且难以理解。
  • 当想创建一个运行于多个类之间的对象,又不想生成新的子类时。



2 案例一

【案例】租房

2.1 需求

  现在租房基本都是通过房屋中介,房主将房屋托管给房屋中介,而租房者从房屋中介获取房屋信息。房屋中介充当租房者与房屋所有者之间的中介者。

  类图如下:

在这里插入图片描述

2.2 代码实现

抽象中介者类(抽象类)
/**
 * 抽象中介者类
 *
 * @author LiaoYuXing-Ray
 **/
public abstract class Mediator {
    // 沟通
    public abstract void contact(String message, Person person);
}

抽象同事类(抽象类)
/**
 * 抽象同事类
 *
 * @author LiaoYuXing-Ray
 **/
public abstract class Person {

    // 租房者或者房主的姓名
    protected String name;
    // 中介
    protected Mediator mediator;

    public Person(String name, Mediator mediator) {
        this.name = name;
        this.mediator = mediator;
    }
}
具体的同事角色类(类)
/**
 * 具体的同事角色类
 *
 * @author LiaoYuXing-Ray
 **/
public class HouseOwner extends Person {

    public HouseOwner(String name, Mediator mediator) {
        super(name, mediator);
    }

    // 和中介联系(沟通)
    public void contact(String message) {
        mediator.contact(message,this);
    }

    // 获取信息
    public void getMessage(String message) {
        System.out.println("房主" + name + "获取到的信息是:" + message);
    }
}
具体的同事角色类(类)
/**
 * 具体的同事角色类
 *
 * @author LiaoYuXing-Ray
 **/
public class Tenant extends Person {
    public Tenant(String name, Mediator mediator) {
        super(name, mediator);
    }

    // 和中介联系(沟通)
    public void contact(String message) {
        mediator.contact(message,this);
    }

    // 获取信息
    public void getMessage(String message) {
        System.out.println("租房者" + name + "获取到的信息是:" + message);
    }
}
具体的中介者角色类(类)
/**
 * 具体的中介者角色类
 *
 * @author LiaoYuXing-Ray
 **/
public class MediatorStructure extends Mediator {

    // 聚合房主和租房者对象
    private HouseOwner houseOwner;
    private Tenant tenant;

    public HouseOwner getHouseOwner() {
        return houseOwner;
    }

    public void setHouseOwner(HouseOwner houseOwner) {
        this.houseOwner = houseOwner;
    }

    public Tenant getTenant() {
        return tenant;
    }

    public void setTenant(Tenant tenant) {
        this.tenant = tenant;
    }

    public void contact(String message, Person person) {
        if(person == houseOwner) {
            tenant.getMessage(message);
        } else {
            houseOwner.getMessage(message);
        }
    }
}
测试类
/**
 * 测试类
 *
 * @author LiaoYuXing-Ray
 **/
public class Client {
    public static void main(String[] args) {
        // 创建中介者对象
        MediatorStructure mediator = new MediatorStructure();

        // 创建租房者对象
        Tenant tenant = new Tenant("李四",mediator);

        // 创建房主对象
        HouseOwner houseOwner = new HouseOwner("张三",mediator);

        // 中介者要知道具体的房主和租房者
        mediator.setTenant(tenant);
        mediator.setHouseOwner(houseOwner);

        tenant.contact("要租三室的房子!!!");
        houseOwner.contact("我这里有三室的房子,你要租吗?");
    }
}

  代码运行结果如下:

	房主张三获取到的信息是:要租三室的房子!!!
	租房者李四获取到的信息是:我这里有三室的房子,你要租吗?

3 案例二

本案例为菜鸟教程中的案例

3.1 需求

  我们通过聊天室实例来演示中介者模式。实例中,多个用户可以向聊天室发送消息,聊天室向所有的用户显示消息。我们将创建两个类 ChatRoom 和 User。User 对象使用 ChatRoom 方法来分享他们的消息。

  MediatorPatternDemo,我们的演示类使用 User 对象来显示他们之间的通信。

在这里插入图片描述

(原图就这么糊)

3.2 代码实现

步骤 1

  创建中介类。

ChatRoom.java
import java.util.Date;
 
public class ChatRoom {
   public static void showMessage(User user, String message){
      System.out.println(new Date().toString()
         + " [" + user.getName() +"] : " + message);
   }
}

步骤 2

  创建 user 类。

User.java
public class User {
   private String name;
 
   public String getName() {
      return name;
   }
 
   public void setName(String name) {
      this.name = name;
   }
 
   public User(String name){
      this.name  = name;
   }
 
   public void sendMessage(String message){
      ChatRoom.showMessage(this,message);
   }
}

步骤 3

  使用 User 对象来显示他们之间的通信。

MediatorPatternDemo.java
public class MediatorPatternDemo {
   public static void main(String[] args) {
      User robert = new User("Robert");
      User john = new User("John");
 
      robert.sendMessage("Hi! John!");
      john.sendMessage("Hello! Robert!");
   }
}

步骤 4

  执行程序,输出结果:

	Thu Jan 31 16:05:46 IST 2013 [Robert] : Hi! John!
	Thu Jan 31 16:05:46 IST 2013 [John] : Hello! Robert!



本文是博主的粗浅理解,可能存在一些错误或不完善之处,如有遗漏或错误欢迎各位补充,谢谢

  如果觉得这篇文章对您有所帮助的话,请动动小手点波关注💗,你的点赞👍收藏⭐️转发🔗评论📝都是对博主最好的支持~


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/501637.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JAVA】Idea 右侧的gradle 不见了

1. 找到项目的build.gradle 文件,右键 2. 找到“Link Gradle Project”选项 3. 右侧就出现了gradle

记录一个写自定义Flume拦截器遇到的错误

先说结论: 【结论1】配置文件中包名要写正确 vim flume1.conf ... a1.sources.r1.interceptors.i1.type com.atguigu.flume.interceptor.MyInterceptor2$MyBuilder ... 标红的是包名,表黄的是类名,标蓝的是自己加的内部类名。这三个都…

wiztree免费的c盘清理软件

现如今,我们无论是工作还是学习,都已经离不开电脑了,经常使用电脑就会导致电脑的“垃圾”越来越多,从而导致磁盘爆红。 相信大家多多少少都体会过这大红的压迫感吧,想清理但是不敢删,不清理吧软件用不了&a…

ArcGIS支持下SWAT与CENTURY模型的结合:流域水碳氮综合模拟

目录 专题一 流域水碳氮建模 专题二 数据准备 专题三 流域水模拟 专题四 流域氮模拟 专题五 流域碳模拟 专题六 模型结果分析及地图制作 更多应用 基于ArcGIS的SWAT模型是一类比较典型的流域模型,结合SWAT模型和生物地球化学循环模型可以实现流域水碳氮综合模…

1.1 单片机的概念

一,单片机的概念 单片机(Single-Chip Microcomputer),也被称为单片微控制器,是一种集成电路芯片。它采用超大规模集成电路技术,将具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、…

怎么让ChatGPT批量写作原创文章

随着人工智能技术的不断发展,自然语言处理模型在文本生成领域的应用也日益广泛。ChatGPT作为其中的佼佼者之一,凭借其强大的文本生成能力和智能对话特性,为用户提供了一种高效、便捷的批量产出内容的解决方案。以下将就ChatGPT批量写作内容进…

蓝桥杯第十五届抱佛脚(五)DFS、BFS及IDS

蓝桥杯第十五届抱佛脚(五)DFS、BFS及IDS 深度优先搜索 DFS(Depth-First Search)即深度优先搜索,是一种用于遍历或搜索树或图的算法。它从根节点开始,尽可能沿着每一条路径直到这条路径最后一个节点被访问了,然后回退,继续访问下一条路径。它的基本思想…

亚米级分辨率卫星原始影像免费了

免费申请亚米级分辨率卫星原始影像(限学生) 引言 今天我去参加了长光卫星公司在北京举行的一个培训班,看到了一个宣传栏,挺有意思的,分享一下: 就是吉林长光给高校用户的一个影像福利,用来促进吉林一号的应用,你用长…

vue3+ts项目 | axios 的测试 | 测试接口

在 App.vue 中,测试接口 // 测试接口import request from /utils/request;import { onMounted } from vue;onMounted(() > {request.get(/hosp/hospital/1/10).then((res) > {console.log("APP组件展示获取的数据",res);})}) 在request.ts中&…

登录者个人信息查询

目录 🥞1.vo层描述 🍿2..vo层创建 🌭3.编写controller层 🥓4.service层 🧂5.测试 1.vo层描述 Spring Boot项目中的实体类通常用于映射数据库表,包含了业务对象的所有属性。然而,前端或其…

C#手术麻醉系统源码 大型医院手麻系统4大需求是什么?

C#手术麻醉系统源码 大型医院手麻系统4大需求是什么? 手术麻醉临床信息系统有着完善的临床业务功能,能够涵盖整个围术期的工作,能够采集、汇总、存储、处理、展 现所有的临床诊疗资料。通过该系统的实施,能够规范手麻科的工作流程…

SD-WAN异地组网的实施步骤

SD-WAN的异地组网实施步骤可以分为几个关键阶段,每个阶段都需要仔细规划和有效执行。以下是一个基本的SD-WAN异地组网实施步骤: 1、网络评估和规划 在开始SD-WAN的异地组网实施之前,需要对现有网络进行评估,了解网络拓扑、连接情…

【web安全】Dr4g0n-b4ll 靶场笔记

搜索目标,使用:nmap -sn 192.168.111.0/24 扫描当前ip段的存货 -sn是忽略端口,只扫描存活,发现IP:192.168.111.133 先不要扫描,直接访问:192.168.111.133,打开是普通的网页 观察内容…

并发编程之CountDownLatch和CyclicBarrier的详细解析(带小案例)

CountDownLatch 倒计时锁存器 用来解决线程执行次序的问题 CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞。 其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞), 当计数器的值变为…

蓝桥杯刷题_day7_动态规划_路径问题

文章目录 DAY7下降路径最小和最小路径和地下城游戏 DAY7 下降路径最小和 【题目描述】 给你一个 n x n 的 方形 整数数组 matrix ,请你找出并返回通过 matrix 的下降路径 的 最小和 。 下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元…

基于Websocket的局域网聊天系统

1.1 研究背景及意义 本项目所对应领域的研究背景及意义[1]。新冠肺炎局域网通信发生以来,大数据、云计算、人工智能等新一代信息技术加速与交通、局域网通信、教育、金融等领域深度融合,让局域网通信防控的组织和执行更加高效,成为战“疫”的…

C++王牌结构hash:哈希表开散列(哈希桶)的实现与应用

目录 一、开散列的概念 1.1开散列与闭散列比较 二、开散列/哈希桶的实现 2.1开散列实现 哈希函数的模板构造 哈希表节点构造 开散列增容 插入数据 2.2代码实现 一、开散列的概念 开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址&…

Day57:WEB攻防-SSRF服务端请求Gopher伪协议无回显利用黑白盒挖掘业务功能点

目录 SSRF-原理&挖掘&利用&修复 SSRF无回显解决办法 SSRF漏洞挖掘 SSRF协议利用 http:// (常用) file:/// (常用) dict:// (常用) sftp:// ldap:// tftp:// gopher:// (…

使用AOP实现打印日志

首先创建annotation.SystemLog类: package com.gjh.annotation;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;Target(ElementType.METHOD…

深度学习pytorch——nn.Module(持续更新)

作为一个初学者,发现构建一个简单的线性模型都能看到nn.Module的身影,初学者疑惑了,nn.Module到底是干什么的,如此形影不离,了解之后,很牛。 1、nn.Module是所有层的父类,比如Linear、BatchNor…