中介者模式详解:概念、优点及实例

news2024/12/28 23:01:13

目录

  • 中介者模式
    • 中介者模式结构
    • 中介者模式适用场景
    • 中介者模式优缺点
    • 练手题目
      • 题目描述
      • 输入描述
      • 输出描述
      • 题解

中介者模式

中介者模式是一种行为设计模式, 能让你减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行合作。

中介者模式结构

在这里插入图片描述

  1. 组件 (Component) 是各种包含业务逻辑的类。 每个组件都有一个指向中介者的引用, 该引用被声明为中介者接口类型。 组件不知道中介者实际所属的类, 因此你可通过将其连接到不同的中介者以使其能在其他程序中复用。

  2. 中介者 (Mediator) 接口声明了与组件交流的方法, 但通常仅包括一个通知方法。 组件可将任意上下文 (包括自己的对象) 作为该方法的参数, 只有这样接收组件和发送者类之间才不会耦合。

  3. 具体中介者 (Concrete Mediator) 封装了多种组件间的关系。 具体中介者通常会保存所有组件的引用并对其进行管理, 甚至有时会对其生命周期进行管理。

  4. 组件并不知道其他组件的情况。 如果组件内发生了重要事件, 它只能通知中介者。 中介者收到通知后能轻易地确定发送者, 这或许已足以判断接下来需要触发的组件了。

    对于组件来说, 中介者看上去完全就是一个黑箱。 发送者不知道最终会由谁来处理自己的请求, 接收者也不知道最初是谁发出了请求。

中介者模式通用代码:

//抽象中介者
abstract class Mediator{
    //定义同事类
    protected List<Colleague> colleagues = new ArrayList<>();
    
    public void addColleague(Colleague colleague){
    colleagues.add(colleague);    
    }
    
    public abstract void sendMessage(String message,Colleague sender);
}

//具体中介类,一般只有一个。
class ConcreteMediator extends Mediator{
    @Override
    public void sendMessage(String message, Colleague sender) {
        for (Colleague colleague : colleagues) {
            if (colleague != sender) {
                colleague.receiveMessage(message);
            }
        }
    }
}

//抽象同事类
abstract class Colleague{
    protected Mediator mediator;
    public Colleague(Mediator mediator){
    this.mediator = mediator;
    mediator.addColleague(this);
}
    public abstract void sendMessage(String name);
    public abstract void receiveMessage(String message);
}

// 具体同事类1
class ConcreteColleague1 extends Colleague {
    public ConcreteColleague1(Mediator mediator) {
        super(mediator);
    }

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

    @Override
    public void receiveMessage(String message) {
        System.out.println("Colleague1 received: " + message);
    }
}

// 具体同事类2
class ConcreteColleague2 extends Colleague {
    public ConcreteColleague2(Mediator mediator) {
        super(mediator);
    }

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

    @Override
    public void receiveMessage(String message) {
        System.out.println("Colleague2 received: " + message);
    }
}

中介者模式适用场景

  1. 当一些对象和其他对象紧密耦合以致难以对其进行修改时, 可使用中介者模式。

    该模式让你将对象间的所有关系抽取成为一个单独的类, 以使对于特定组件的修改工作独立于其他组件。

  2. 当组件因过于依赖其他组件而无法在不同应用中复用时, 可使用中介者模式。

    应用中介者模式后, 每个组件不再知晓其他组件的情况。 尽管这些组件无法直接交流, 但它们仍可通过中介者对象进行间接交流。 如果你希望在不同应用中复用一个组件, 则需要为其提供一个新的中介者类。

  3. 如果为了能在不同情景下复用一些基本行为, 导致你需要被迫创建大量组件子类时, 可使用中介者模式。

    由于所有组件间关系都被包含在中介者中, 因此你无需修改组件就能方便地新建中介者类以定义新的组件合作方式。
    在这里插入图片描述

中介者模式优缺点

中介者模式优点:

  • 单一职责原则。 你可以将多个组件间的交流抽取到同一位置, 使其更易于理解和维护。

  • 开闭原则。 你无需修改实际组件就能增加新的中介者。

  • 你可以减轻应用中多个组件间的耦合情况。

  • 你可以更方便地复用各个组件。

中介者模式缺点:

  • 中介者会膨胀得很大,逻辑复杂。一段时间后,可能会演化为上帝对象。

练手题目

题目描述

小明正在设计一个简单的多人聊天室系统,有多个用户和一个聊天室中介者,用户通过中介者进行聊天,请你帮他完成这个系统的设计。

输入描述

第一行包括一个整数N,表示用户的数量(1 <= N <= 100) 第二行是N个用户,比如User1 User2 User3,用空格分隔 第三行开始,每行包含两个字符串,表示消息的发出者和消息内容,用空格分隔

输出描述

对于每个用户,输出一行,包含该用户收到的所有消息内容。

在这里插入图片描述

题解

初始解法:

import java.util.*;

// 抽象中介者类
abstract class Mediator {
    protected List<Colleague> colleagues = new ArrayList<>();
    
    // 添加同事到列表
    public void addColleague(Colleague colleague) {
        colleagues.add(colleague);
    }
    
    // 抽象方法:发送消息
    public abstract void sendMessage(String name, String message, Colleague sender);
}

// 具体中介者类
class ConcreteMediator extends Mediator {
    // 实现发送消息方法
    @Override
    public void sendMessage(String name, String message, Colleague sender) {
        // 遍历所有同事,将消息发送给除了发送者之外的所有人
        for (Colleague c : colleagues) {
            if (c != sender) {
                c.receiveMessage(name, message);
            }
        }
    }
}

// 抽象同事类
abstract class Colleague {
    protected Mediator mediator;
    protected String name;

    // 构造函数
    public Colleague(String name, Mediator mediator) {
        this.name = name;
        this.mediator = mediator;
        mediator.addColleague(this);
    }

    // 抽象方法:发送消息
    public abstract void sendMessage(String message);
    // 抽象方法:接收消息
    public abstract void receiveMessage(String senderName, String message);
}

// 具体同事类
class ConcreteColleague extends Colleague {
    public ConcreteColleague(String name, Mediator mediator) {
        super(name, mediator);
    }
    
    // 实现发送消息方法
    @Override
    public void sendMessage(String message) {
        mediator.sendMessage(this.name, message, this);
    }
    
    // 实现接收消息方法
    @Override
    public void receiveMessage(String senderName, String message) {
        System.out.println(this.name + " received: " + message);
    }
}

// 主类
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
    
        // 读取用户数量
        int n = scanner.nextInt();
        scanner.nextLine(); 
        // 读取用户名
        String[] users = scanner.nextLine().split(" ");
        
        // 创建中介者
        Mediator mediator = new ConcreteMediator();
        // 创建用于存储同事对象的映射
        Map<String, Colleague> colleagues = new HashMap<>();
        
        // 创建所有用户的同事对象
        for (String user : users) {
            colleagues.put(user, new ConcreteColleague(user, mediator));
        }
        
        // 读取并处理消息
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            String[] parts = line.split(" ", 2);
            if (parts.length < 2) break;
            
            String senderName = parts[0];
            String message = parts[1];
            
            // 获取发送者并发送消息
            Colleague sender = colleagues.get(senderName);
            if (sender != null) {
                sender.sendMessage(message);
            }
        }
        
        scanner.close();
    }
}

优化后:

import java.util.*;

// 中介者接口
interface Mediator {
    void sendMessage(String message, String sender);
    void addUser(User user);
}

// 具体中介者
class ChatMediator implements Mediator {
    private List<User> users = new ArrayList<>();

    @Override
    public void sendMessage(String message, String sender) {
        for (User user : users) {
            if (!user.getName().equals(sender)) {
                user.receive(message);  
            }
        }
    }

    @Override
    public void addUser(User user) {
        users.add(user);
    }
}

// 用户接口
interface User {
    void send(String message);
    void receive(String message);
    String getName();
}

// 具体用户
class ChatUser implements User {
    private String name;
    private Mediator mediator;

    public ChatUser(String name, Mediator mediator) {
        this.name = name;
        this.mediator = mediator;
        mediator.addUser(this);
    }

    @Override
    public void send(String message) {
        mediator.sendMessage(message, this.name);
    }

    @Override
    public void receive(String message) {
        System.out.println(this.name + " received: " + message);
    }

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

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Mediator mediator = new ChatMediator();
        Map<String, User> users = new HashMap<>();

        int n = scanner.nextInt();
        scanner.nextLine(); 
        String[] userNames = scanner.nextLine().split(" ");

        for (String name : userNames) {
            users.put(name, new ChatUser(name, mediator));
        }

        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            String[] parts = line.split(" ", 2);
            if (parts.length < 2) break;

            String sender = parts[0];
            String message = parts[1];
            User user = users.get(sender);
            if (user != null) {
                user.send(message);
            }
        }

        scanner.close();
    }
}

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

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

相关文章

windows ssh的登录,私钥权限太开放 WARNING: UNPROTECTED PRIVATE KEY FILE!

问题描述 ssh -i wang -D localhost:1080 wangsg.ks99.topBad permissions. Try removing permissions for user Permissions for xxx are too open. F:\pms\pms-gpg-key\ssh-key\wang>ssh -i wang -D localhost:1080 wangsg.ks99.top Bad permissions. Try removing perm…

查看公网IP的网络出口

文章目录 背景 背景 有时候在各种交易或其他时候&#xff0c;会被问到给我一个公网IP&#xff0c;我来帮你加白名单。 这个怎么怎么获取公网IP呢&#xff0c;在自己本机查看ipconfig或者ifconfig ip a 等命令查到的一般都是局域网的IP&#xff0c;每台机器都需要一个IP来进行对…

【文档智能 RAG】RAG新基建-RAG性能增强关键技术点及通用文档解析工具-TextIn

前言 在私有领域知识问答和企业知识管理领域&#xff0c;结合检索增强型生成模型&#xff08;Retrieval-Augmented Generation, RAG&#xff09;大模型&#xff08;Large Language Model, LLM&#xff09;已成为一种趋势。然而&#xff0c;在RAG系统的文档预处理阶段和检索阶段…

【Elasticsearch7】3-基本操作

目录 RESTful 数据格式 HTTP操作 索引操作 倒排索引 创建索引 查看所有索引 查看单个索引 删除索引 文档操作 创建文档 查看文档 ​编辑 全量修改 ​编辑局部修改 删除文档 条件删除文档 高级查询 条件查询 URL带参查询 请求体带参查询 带请求体方式的查…

STM32的ADC详解

目录 一、ADC简介 二、ADC的时钟 三、ADC特性 四、ADC功能说明 五、规则通道和注入通道 1.规则通道 2.注入通道 3.区别 六、数据寄存器 1.右对齐 2.左对齐 七、转换模式 1.单次转换模式 2.续转换模式 3.扫描模式 4.区别 八、程序实现 1.需求 2.ADC初始化 3.A…

InfiniBand网络-赋能高性能计算的卓越引擎

InfiniBand&#xff1a;赋能高性能计算网络的卓越引擎 InfiniBand作为一种先进的内网计算平台&#xff0c;已成为驱动高性能计算&#xff08;HPC&#xff09;、人工智能&#xff08;AI&#xff09;以及超大规模云基础设施演进的核心力量&#xff0c;其展现出无可比拟的性能优势…

mongodb数据导出与导入

一、先去检查mongodump mongodump --version 如果报 mongodump version: built-without-version-string 或者其他的较老的版本&#xff0c;直接去下载最新的【传送门】 【以Ubuntu18.04为例】 安装工具 假设你下载的是 .tgz 文件&#xff08;适用于 Linux 系统&#xff09;&am…

Java中SPI机制原理解析

使用SPI机制前后的代码变化 加载MySQL对JDBC的Driver接口实现 在未使用SPI机制之前&#xff0c;使用JDBC操作数据库的时候&#xff0c;一般会写如下的代码&#xff1a;// 通过这行代码手动加载MySql对Driver接口的实现类 Class.forName("com.mysql.jdbc.Driver") Dr…

鸿蒙开发error: failed to start ability

鸿蒙开发项目编译过后不能启动 项目在模拟器运行报&#xff1a; error: failed to start ability. Error while Launching ability 解决办法&#xff1a; 1&#xff0c;看了一些文章说是把module.json5配置文件中的"exported"由false改成true&#xff0c;没有解…

Python 实现股票指标计算——BIAS

BIAS (Bias Ratio) - 乖离率 1 公式 BIAS (当日收盘价 - N日平均收盘价) ➗ N日平均收盘价 ✖ 100&#xff05; N一般取6、12、24 2 数据准备 我们以科创50指数 000688 为例&#xff0c;指数开始日期为2019-12-31&#xff0c;数据格式如下&#xff1a; 3 计算过程 def c…

Java 中的异常

异常&#xff1a;就是出现的问题。 在Java中异常被当成对象进行处理&#xff0c;所有的异常类都继承于Throwable类&#xff0c;如果Java提供的异常类并不能满足需求&#xff0c;用户还可以自己定义一个异常类。 下面是异常体系结构&#xff1a; Throwable又分成了Error和Exce…

《无所不能的JavaScript · 对象简介》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

OpenStack Yoga版安装笔记(七)glance练习补充

1、练习场景说明 在OpenStack Yoga版安装笔记&#xff08;五&#xff09;中&#xff0c;glance已经在controller node虚拟机上安装完成&#xff0c;并且已经成功拍摄了快照。 此时&#xff0c;controller node虚机已经安装了keystone、keystone DB、glance、glance DB、OpenSta…

利用【MATLAB】和【Python】进行【图与网络模型】的高级应用与分析】

目录 一、图与网络的基本概念 1. 无向图与有向图 2. 简单图、完全图、赋权图 3. 顶点的度 4. 子图与连通性 5. 图的矩阵表示 MATLAB代码实例 Python代码实例 二、最短路径问题 1. 最短路径问题的定义 2. Dijkstra算法 MATLAB代码实例 Python代码实例 三、最小生…

昇思MindSpore学习总结十七 —— 基于MindSpore通过GPT实现情感分类

1、要求 2、导入了一些必要的库和模块 以便在使用MindSpore和MindNLP进行深度学习任务时能使用各种功能&#xff0c;比如数据集处理、模型训练、评估和回调功能。 import os # 导入操作系统相关功能的模块&#xff0c;如文件和目录操作import mindspore # 导入MindSpore库&a…

入门C语言只需一个星期(星期六)

点击上方"蓝字"关注我们 01、创建结构体 struct MyStructure { // 结构声明 int myNum; // 成员&#xff08;int 变量&#xff09; char myLetter; // 成员&#xff08;char 变量&#xff09;}; // 用分号结束结构创建一个名为 s1 的结构变量​struct myStru…

# Redis 入门到精通(九)-- 主从复制(1)

Redis 入门到精通&#xff08;九&#xff09;-- 主从复制&#xff08;1&#xff09; 一、redis 主从复制 – 主从复制简介 1、互联网“三高”架构 高并发高性能高可用 2、你的“Redis”是否高可用&#xff1f; 1&#xff09;单机 redis 的风险与问题 问题1.机器故障  现…

kafka服务介绍

kafka 安装使用管理 Kafka Apache Kafka 是一个开源的分布式事件流平台&#xff0c;主要用于实时数据传输和流处理。它最初由 LinkedIn 开发&#xff0c;并在 2011 年成为 Apache 基金会的顶级项目。Kafka 设计的目标是处理大规模的数据流&#xff0c;同时提供高吞吐量、低延迟…

C语言 通讯录管理 完整代码

这份代码&#xff0c;是我从网上找的。目前是能运行。我正在读。有些不懂的地方&#xff0c;等下再记录下来。 有些地方的命名&#xff0c;还需要重新写一下。 比如: PersonInfo* info &address_book->all_address[address_book->size]; 应该改为&#xff1a; Perso…

C#实现数据采集系统-实现功能介绍

系统介绍 我们这里主要使用C#( .Net 6)来实现一个数据采集系统&#xff0c;从0到1搭建数据采集系统&#xff0c;从系统分析&#xff0c;功能拆解&#xff0c;到一一实现 数据采集 数据采集是企业信息化和数字化转型过程中的关键环节&#xff0c;它涉及到从生产设备、传感器…