行为型模式-中介模式

news2024/11/16 4:52:24

1.概述

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

如果引入中介者模式,那么同事类之间的关系将变为星型结构,从下右图中可以看到,任何一个类的变动,只会影响的类本身,以及中介者,这样就减小了系统的耦合。一个好的设计,必定不会把所有的对象关系处理逻辑封装在本类中,而是使用一个专门的类来管理那些不属于自己的行为。
在这里插入图片描述
定义:又叫调停模式,定义一个中介角色来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。

2.结构

中介者模式包含以下主要角色:

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

3.案例实现

【例】租房

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

类图如下
在这里插入图片描述
代码如下

package com.itheima.pattern.mediator;

/**
 * @program: design-patterns
 * @ClassName Mediator
 * @description: 抽象中介者类
 * @author: 
 * @create: 2023-01-27 08:29
 * @Version 1.0
 **/
public abstract class Mediator {
    public abstract void constact(String message, Person person);
}
package com.itheima.pattern.mediator;

/**
 * @program: design-patterns
 * @ClassName MediatorStructure
 * @description: 具体中介者类
 * @author: 
 * @create: 2023-01-27 08:38
 * @Version 1.0
 **/
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;
    }

    @Override
    public void constact(String message, Person person) {
        if (person == houseOwner) {
            tenant.getMessage(message);
        } else {
            houseOwner.getMessage(message);
        }
    }
}
package com.itheima.pattern.mediator;

/**
 * @program: design-patterns
 * @ClassName Person
 * @description: 抽象同事类
 * @author: 
 * @create: 2023-01-27 08:31
 * @Version 1.0
 **/
public class Person {
    protected String name;
    protected Mediator mediator;

    public Person(String name, Mediator mediator) {
        this.name = name;
        this.mediator = mediator;
    }
}
package com.itheima.pattern.mediator;

/**
 * @program: design-patterns
 * @ClassName Tenant
 * @description: 具体同事角色类
 * @author: 
 * @create: 2023-01-27 08:32
 * @Version 1.0
 **/
public class Tenant extends Person {

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

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

    // 获取信息
    public void getMessage(String message) {
        System.out.println("租房者:" + name + "获取到的租房信息:" + message);
    }
}
package com.itheima.pattern.mediator;

/**
 * @program: design-patterns
 * @ClassName HouseOwner
 * @description:
 * @author: 
 * @create: 2023-01-27 08:35
 * @Version 1.0
 **/
public class HouseOwner extends Person {

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

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

    // 获取信息
    public void getMessage(String message) {
        System.out.println("房主:" + name + "获取到的信息:" + message);
    }
}
package com.itheima.pattern.mediator;

/**
 * @program: design-patterns
 * @ClassName Client
 * @description: 测试类
 * @author: 
 * @create: 2023-01-27 08:42
 * @Version 1.0
 **/
public class Client {
    public static void main(String[] args) {
        // 创建中介者
        MediatorStructure mediator = new MediatorStructure();
        // 创建租房者对象
        Tenant tenant = new Tenant("李四", mediator);
        // 创建房主对象
        HouseOwner houseOwner = new HouseOwner("张三", mediator);

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

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

4.优缺点

  • 优点
    • 松散耦合
      中介者模式通过把多个同事对象之间的交互封装到中介者对象里面,从而使得同事对象之间松散耦合,基本上可以做到互补依赖。这样一来,同事对象就可以独立地变化和复用,而不再像以前那样“牵一处而动全身”了。
    • 集中控制交互
      多个同事对象的交互,被封装在中介者对象里面集中管理,使得这些交互行为发生变化的时候,只需要修改中介者对象就可以了,当然如果是已经做好的系统,那么就扩展中介者对象,而各个同事类不需要做修改。
    • 一对多关联转变为一对一的关联
      没有使用中介者模式的时候,同事对象之间的关系通常是一对多的,引入中介者对象以后,中介者对象和同事对象的关系通常变成双向的一对一,这会让对象的关系更容易理解和实现。
  • 缺点
    • 当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护。

5.使用场景

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode 2325. 解密消息

给你字符串 key 和 message ,分别表示一个加密密钥和一段加密消息。解密 message 的步骤如下: 使用 key 中 26 个英文小写字母第一次出现的顺序作为替换表中的字母 顺序 。 将替换表与普通英文字母表对齐,形成对照表。 按照对照表 替换 mess…

〖产品思维训练白宝书 - 核心竞争力篇⑤〗- 产品经理核心竞争力解读之如何培养创造力

大家好,我是 哈士奇 ,一位工作了十年的"技术混子", 致力于为开发者赋能的UP主, 目前正在运营着 TFS_CLUB社区。 💬 人生格言:优于别人,并不高贵,真正的高贵应该是优于过去的自己。💬 &#x1f4e…

【从零开始】力扣刷题(1)

文章目录前言数组:数组的遍历485.最大连续的一个数495.提莫攻击414.第三大的数628.三个数的最大乘积数组:统计数组中的元素645.错误的集合697.数组的度484.找到所有数组中消失的数组442.数组中重复的数据41.缺失的第一个正数274.H指数前言 我根据这里的…

Scalable SoftGroup for 3D Instance Segmentation on Point Clouds

Abstract 本文考虑了一个称为SoftGroup的网络,用于准确和可扩展的3D实例分割。现有的最先进方法会产生硬语义预测,然后进行分组以获得实例分割结果。然而,源于硬决策的错误会传播到分组中,导致预测实例与ground truth的低重叠和大…

数据结构:排序的基本概念

排序(sorting)是按关键字的非递减或非递增顺序对一组记录重新进行整队(或排列)的操作。确切描述如下: 假设含有 n 个记录的序列为 {r1 ,r2 , … ,rn} (3-1) 它们的关键字相应为 {k1 ,k2 , … ,kn} 对式(3-1)的记录序列进行排序就是要确定序号 1,2,,n 的一种排列 p1,p2 , … …

MyBatis 表连接查询写法|三种对应关系

❤️作者主页:微凉秋意 ✅作者简介:后端领域优质创作者🏆,CSDN内容合伙人🏆,阿里云专家博主🏆 ✨精品专栏:C面向对象 🔥系列专栏:JavaWeb 文章目录前言表连接…

JS 6万字超详细总结

文章目录1. JS简介2. JS的使用2.1 行内式2.2 内嵌式2.3 外部式3. JS基础语法3.1 注释3.2 变量3.3 输入和输出3.4 数据类型3.4.1 字符串类型3.4.2 数字类型3.4.3 布尔类型3.4.4 Undefined和Null3.4.5 获取变量的类型3.5 数据类型转换3.5.1 转换为字符串类型3.5.2 转换为数字类型…

Java多线程(二)——ReentrantLock源码解析(补充4——条件变量Condition)

ReentrantLock源码解析(补充4——条件变量Condition) 上一章 ReentrantLock源码解析 仅介绍了 ReentrantLock 的常用方法以及公平锁、非公平锁的实现。这里对上一章做一些补充。主要是: AQS 中阻塞的线程被唤醒后的执行流程可打断的锁 lock…

CDH数仓项目(二) —— 用户行为数仓和业务数仓搭建

0 说明 本文基于《CDH数仓项目(一) —— CDH安装部署搭建详细流程》开始搭建数仓 1 数仓搭建环境准备 1.1 Flume安装部署 1)添加服务 2) 选择Flume 3)选择依赖 4)选择部署节点 5) 安装完成 1.2 安装Sqoop 1)添加服务 2)选…

Unity2023 Alpha新功能简介

Unity2023特征:Graphic:添加了新的光线跟踪加速结构。添加实例签名,允许将网格实例添加到GPU光线跟踪的加速结构中。从栅格化管道中渲染网格。HDRP:为HDRP添加了光线追踪地形支持。Eidtor:添加了“聚焦窗口改变”回调到…

spring AOP 原理

一、spring注册 AnnotationAwareAspectJAutoProxyCreator 通过EnableAspectJAutoProxy可以看到先把AspectJAutoProxyRegistrar通过Import注册到spring。 AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,所以就有了将某个bean引入spring 的能力…

#C. 笨友圈

题目思路1直接模拟题意,相当于邻接矩阵,用bool类型的二维数组vis[i][j]来存储i和j是否为好友,交叉点为1代表是好友,为0代表不是;a[i]存储i这个人看到的信息数量。然后输入后如果符号代表要将u,v加个好友,就将vis[u][v] 1和vis[v][u] 1,如果是拉黑就将vis[u][v] 0和vis[v][u]…

ATAC-seq分析:差异分析(10)

在下部分中,我们将研究如何使用 R/Bioconductor 识别开放区域中的变化。 在这里,我们将采用类似于 Diffbind 中的方法,并在 ATACseq 分析中合理建立。 1. 识别非冗余峰 首先,我们将定义至少 2 个样本中存在的一组非冗余峰&#xf…

ffmpeg为mkv封装格式的音视频文件添加字幕

现在好莱坞的电影,都是全球看,一个地区的人看电影时,电影屏幕上应该展示对应的本地区语言字幕。故电影画面在不同的地区,需要配置不同的语言字幕。故视频画面里面的字幕应该可以拆出来,不能像老版三国演义,…

ZYNQ IP核之RAM

随机存取存储器(Random Access Memory,RAM),可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址中读出数据,其读写速度是由时钟频率决定的,主要用来存放程序及程序执行过程中产…

C++结构(OOP的基石)

写在前面 面向初学者撰写专栏,个人原创的学习C/C笔记(干货)所作源代码输出内容为中文,便于理解如有错误之处请各位读者指正请读者评论回复、参与投票,反馈给作者,我会获得持续更新笔记干货的动力。致粉丝&a…

vulnhub之VENOM:1

1.信息收集 输入arp-scan 192.168.239.0/24探测存活的IP 使用nmap对192.168.239.166进行扫描,发现IP端口21、80、139、443、445。 在浏览器上访问http://192.168.239.166/,查看源码发现类似md5加密。 解密md5可以得到为hostinger。 输入enum4linux …

Linux | 软件包管理器——yum的使用

文章目录一、什么是软件包二、有关软件使用的背景讲解1、如何去下一个软件呢?过程是怎样的?2、软件的商业利益分析3、Linux开源社区的生态链4、Linux中软件的分类和选择三、yum的使用1、说在前面【注意事项】2、如何查看软件包3、软件的安装和卸载四、yu…

WPF鼠标、键盘、拖拽事件、用行为封装事件

WPF鼠标、键盘、拖拽事件、用行为封装事件 本文主要介绍了WPF中常用的鼠标事件、键盘事件以及注意事项,同时使用一个案例讲解了拓展事件。除此之外,本文还讲述如何用行为(Behavior)来封装事件。 Windows中的事件通过消息机制来完…

新手利用Git上传项目代码到Gitee仓库

【本文发布于https://blog.csdn.net/Stack_/article/details/128770678,未经许可禁止转载,转载须注明出处】 一、安装git工具 【git下载】 【git插件以及插件汉化包下载】 官网下载很慢,已上传CSDN。跳转 或者百度云 链接:https:…