【设计模式-4.8】行为型——中介者模式

news2025/7/26 13:28:26

说明:本文介绍行为型设计模式之一的中介者模式

定义

中介者模式(Mediator Pattern)又叫作调节者模式或调停者模式。用一个中介对象封装一系列对象交互,中介者使各对象不需要显式地互相作用,从而使其耦合松散,而且可以独立地改变它们之间的交互,属于行为型设计模式。

(引自《设计模式就该这样学》P376)

中介者模式简单来说,就是引入中间层,让多对多关系,转为多个一对多关系,图示如下:

(多对多场景)

在这里插入图片描述

(引入中间层,转为多个一对多)

在这里插入图片描述

这样符合迪米特法则(指一个软件实体应当尽可能少地与其他实体发生相互作用),这样,当一个模块修改时,就会尽量少地影响其他的模块。

通讯交友

以两人通讯为例,如下,

(用户类,User)

/**
 * 用户类
 */
public class User {

    /**
     * 自己的名字
     */
    private String name;

    /**
     * 定义通话对方
     */
    private User friend;

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    /**
     * 建立连接
     */
    public void connect(User friend) {
        this.friend = friend;
    }

    /**
     * 说话
     * 我方说话,调用对方的listen方法
     */
    public void talk(String msg) {
        friend.listen(msg);
    }

    /**
     * 接听
     */
    private void listen(String msg) {
        System.out.println(friend.name + " 对 " + name + " 说:" + msg);
    }
}

(客户端使用,进行聊天)

public class Client {
    public static void main(String[] args) {
        User zhangsan = new User("zhangsan");
        User lisi = new User("lisi");

        zhangsan.connect(lisi);
        lisi.connect(zhangsan);

        zhangsan.talk("hello,四哥,我是三哥啊,您最近挺好的啊?");
        lisi.talk("哦,三哥啊,我以为谁呢,我挺好的,您呢?");
    }
}

开始通话

在这里插入图片描述

现在只有两个人,这种设计看起来没有问题,但如果有十个人,开一场多人会议,就要在对象内维护一个User集合,而会议人数新增或减少时,要同时改动每个对象中的User集合,这非常繁琐还容易出问题。

聊天室

基于上面代码的问题,我们引入一个中间层(聊天室),如下:

(用户类,User,定义一个所属聊天室)

/**
 * 用户类
 */
public class User {

    /**
     * 自己的名字
     */
    private String name;

    /**
     * 所属聊天室
     */
    private Chatroom chatRoom;

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    /**
     * 加入群聊
     */
    public void login(Chatroom chatRoom) {
        this.chatRoom = chatRoom;
        chatRoom.register(this);
    }

    /**
     * 群内发言
     */
    public void talk(String msg) {
        chatRoom.sendMsg(this, msg);
    }

    /**
     * 接收消息
     */
    public void listen(User fromUser, String msg) {
        System.out.println("【" + this.name + "】的聊天框 【" + fromUser.getName()  + "】说:" + msg);
    }
}

(聊天室,用来管理群成员,发消息等操作)

import java.util.ArrayList;
import java.util.List;

/**
 * 聊天室
 */
public class Chatroom {

    /**
     * 群名称
     */
    private String name;

    public Chatroom(String name) {
        this.name = name;
    }

    /**
     * 群内好友
     */
    private List<User> users = new ArrayList<>();

    /**
     * 好友加入群聊
     */
    public void register(User user) {
        this.users.add(user);
        System.out.println("【系统消息】" + user.getName() + "进入群聊");
    }

    /**
     * 群内发消息
     */
    public void sendMsg(User fromUser, String msg) {
        users.stream().forEach(user -> user.listen(fromUser, msg));
        System.out.println("-------------------------------------------------");
    }
}

(客户端测试,Client)

public class Client {
    public static void main(String[] args) {
        // 创建群,好友
        Chatroom chatroom = new Chatroom("各位IT界的大佬们");
        User zhangsan = new User("zhangsan");
        User lisi = new User("lisi");
        User wangwu = new User("王五");

        // 好友加入群聊
        zhangsan.login(chatroom);
        lisi.login(chatroom);

        // 发消息
        zhangsan.talk("hello,四哥,群里就你一个人啊");
        lisi.talk("是啊,把五哥拉进来");

        // 拉人进群
        wangwu.login(chatroom);

        // 发消息
        zhangsan.talk("哇,五哥来了");
        wangwu.talk("哥几个,怎么说");
    }
}

怎么样,这样设计是不是好多了,结构一下就稳定了,无论群成员增加还是减少,现有代码都不用改动。

在这里插入图片描述

使用场景

在《设计模式就该这样学》(P378)这本书中,提到状态模式适用于以下场景:

(1)系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。

(2)交互的公共行为,如果需要改变行为,则可以增加新的中介者类。

中介者模式,在Java三层结构开发中就有体现,Service层不会直接访问数据库,而是抽出DAO层,使用DAO对象访问数据库,就是中介者模式的一种体现,还有Spring IOC容器也是,将Bean的创建使用抽离出来统一管理。

还有,有时我们业务中,有种业务场景,没有与之对应的实体(像User对应UserService、UserDAO),而是业务逻辑中产生的对象,如CheckService(检查服务,根据日志表、用户表,检查用户状态是否正常),我们不直接在UserService里实现,而是抽出一个CheckService,这也是中介者模式的一种实现。

总结

本文介绍了行为型设计模式中的中介者模式,参考《设计模式就该这样学》、《秒懂设计模式》两书,通讯交友、聊天室场景是《秒懂设计模式》中的举例。

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

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

相关文章

行列式的性质

1 行列式使用如下性质定义 1&#xff09;单位矩阵行列式值为 1&#xff0c; &#xff0c;对于任意单位矩阵均成立&#xff1b; 2&#xff09;当矩阵交换一行后&#xff0c;行列式值改变符号&#xff0c;如置换矩阵的行列式值为 &#xff08;根据行交换次数决定&#xff09;&…

联软NSPM自动化策略管理 助力上交所加速国产化替代提升运维效率

在金融行业核心基础设施国产化浪潮与网络安全强监管的双重背景下&#xff0c;上海证券交易所&#xff08;以下简称“上交所”&#xff09;积极拥抱变革&#xff0c;携手长期合作伙伴联软科技&#xff0c;成功部署了联软安全策略管理系统&#xff08;NSPM&#xff09;。该项目不…

Flask + ECharts+MYSQL物联网数字化大屏

基于Flask+ECharts的物联网数字化大屏系统,包含中国地图实时数据更新功能。这个系统模拟了物联网设备在全国范围内的分布和运行状况,并实时更新数据。 一、系统架构设计 技术栈 后端:Flask(轻量级路由+API支持) 前端:ECharts(地图+动态图表)、WebSocket(实时更新)…

数据库系统概论(十六)数据库安全性(安全标准,控制,视图机制,审计与数据加密)

数据库系统概论&#xff08;十六&#xff09;数据库安全性 前言一、数据库安全性1. 什么是数据库安全性&#xff1f;2. 为何会存在安全问题&#xff1f; 二、安全标准的发展1. 早期的“开拓者”&#xff1a;TCSEC标准2. 走向国际统一&#xff1a;CC标准3. TCSEC和CC标准有什么不…

vue3从入门到精通(基础+进阶+案例)

Vue是什么&#xff1f; 渐进式JavaScript框架&#xff0c;易学易用&#xff0c;性能出色&#xff0c;适用场景丰富的Web前端框架 为什么要学习Vue Vue是目前前端最火的框架之一 Vue是目前企业技术栈中要求的知识点 Vue可以提升开发体验 。。。 Vue简介 Vue(发音为/vju/,…

【Linux 学习计划】-- 系统中进程是如何调度的(内核进程调度队列)

目录 回顾进程优先级与进程调度的引入 内核runqueue图例 关于queue[140]前100个位置 | 实时进程与分时进程 遍历需要调度的进程与bitmap的引入 active、expired指针 结语 回顾进程优先级与进程调度的引入 在我们之前的学习中&#xff0c;我们是有学习过进程优先级这个概…

C#、VB.net——如何设置窗体应用程序的外边框不可拉伸

以Visual studio 2015为例&#xff0c;具体操作如下&#xff1a; 1、将窗体的“FormBorderStyle”属性值修改为“FixedSingle”&#xff1a; 2、点击“格式”——“锁定控件”&#xff1a; 这样生成的程序边框即可固定住&#xff0c;无法拉伸。

基于SpringBoot的房屋租赁系统的设计与实现(thymeleaf+MySQL)

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

Spring Boot统一功能处理深度解析

第一章&#xff1a;为什么需要统一功能处理&#xff1f; 想象你正在开发一个电商系统&#xff0c;包含用户管理、商品管理、订单管理等模块。每个模块都需要&#xff1a; 用户身份验证操作日志记录异常统一处理数据格式标准化 如果每个模块都单独实现这些功能&#xff1a; …

世事无常,比较复杂,人可以简单一点

2025年6月5日日&#xff0c;17~28℃&#xff0c;一般 待办&#xff1a; 宣讲会 职称材料的最后检查 职称材料有错误&#xff0c;需要修改 期末考试试题启用 教学技能大赛PPT 遇见&#xff1a;部门宣传泰国博士项目、硕士项目、本科项目。 感受或反思&#xff1a;东南亚博士…

数据结构哈希表总结

349. 两个数组的交集 力扣题目链接(opens new window) 题意&#xff1a;给定两个数组&#xff0c;编写一个函数来计算它们的交集。 说明&#xff1a; 输出结果中的每个元素一定是唯一的。 我们可以不考虑输出结果的顺序。 public int[] intersection(int[] nums1, int[] num…

IDEA 开发PHP配置调试插件XDebug

1、安装PHP环境 为了方便&#xff0c;使用的PhpStudy。 安装路径&#xff1a;D:\resources\phpstudy_pro\Extensions\php\php7.3.4nts 2、下载Xdebug Xdebug: Downloads 选择对应的版本下载&#xff0c;本次使用的是7.3。 3、配置Xdebug 在php.ini中添加Xdebug配置。 D…

奇异值分解(SVD):线性代数在AI大模型中的核心工具

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;10年以上C/C, C#, Java等多种编程语言开发经验&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开…

MySQL——视图 用户管理 语言访问

目录 视图 用户管理 数据库权限 访问 准备工作 使用函数 mysql界面级工具 连接池 视图 这里的视图与事务中的读视图是两个不同的概念&#xff1a;视图是一个虚拟表&#xff0c;其内容由查询定义。同真实的表一样&#xff0c;视图包含一系列带有名称的列和行数据。视图的…

二、Sqoop 详细安装部署教程

作者&#xff1a;IvanCodes 日期&#xff1a;2025年6月2日 专栏&#xff1a;Sqoop教程 Apache Sqoop 是一个强大的工具&#xff0c;用于在 Hadoop (HDFS, Hive, HBase) 与关系型数据库 (如 MySQL, PostgreSQL, Oracle) 之间高效传输数据。本教程将详细指导您如何根据官方网站截…

【C语言预处理详解(下)】--#和##运算符,命名约定,命令行定义 ,#undef,条件编译,头文件的包含,嵌套文件包含,其他预处理指令

目录 五.#和##运算符 5.1--#运算符 5.2--##运算符 六.命名约定&#xff0c;#undef&#xff0c;命令行定义 6.1--命名约定 6.2--#undef 6.3--命名行定义 七.条件编译 常见的条件编译指令&#xff1a; 1.普通的条件编译&#xff1a; 2.多个分支的条件编译(可以利用条…

03.搭建K8S集群

K8S集群搭建的方式 目前主流的搭建k8s集群的方式有kubeadm、minikube、二进制包三种方式&#xff1a; kubeadm&#xff08;本案例搭建方式&#xff09; 是一个工具&#xff0c;用于快速搭建kubernetes集群&#xff0c;目前应该是比较方便和推荐的&#xff0c;简单易用 kubea…

RDMA简介3之四种子协议对比

RDMA协议共有四种子协议&#xff0c;分别为InfiniBand、iWARP、RoCE v1和RoCE v2协议。这四种协议使用统一的RDMA API&#xff0c;但在具体的网络层级实现上有所不同&#xff0c;如图1所示&#xff0c;接下来将分别介绍这四种子协议。 图1 RDMA四种子协议网络层级关系图 Infin…

【最新版】西陆洗车系统源码全开源+uniapp前端+搭建教程

一.系统介绍 一款基于ThinkPHPUniapp开发的多门店洗车系统&#xff0c;包含用户端&#xff08;小程序&#xff09;、门店员工端&#xff08;小程序&#xff09;、门店端&#xff08;PC&#xff09;、平台管理端&#xff08;PC&#xff09;。 门店分连锁门店和独立门店&#xf…

Linux开发工具(apt,vim,gcc)

目录 yum/apt包管理器 Linux编辑器 vim 1.见一见vim 2.vim的多模式 3.命令模式底行模式等 4.vim的配置 Linux编译器 gcc/g 1.预处理&#xff08;宏替换&#xff09; 2.编译&#xff08;生成汇编&#xff09; 3.汇编&#xff08;生成机器可识别代码&#xff09; 4.连…