中介者模式的理解和实践

一、中介者模式概述

        中介者模式(Mediator Pattern),也称为调解者模式或调停者模式,是一种行为设计模式。它的核心思想是通过引入一个中介者对象来封装一系列对象之间的交互,使得这些对象不必直接相互作用,从而达到松散耦合的效果。这种设计模式主要用于降低系统中对象之间的耦合度,提高系统的灵活性和可维护性。

        中介者模式定义了一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,并且可以独立地改变它们之间的交互。在这个模式中,各个对象不再直接相互引用和通信,而是通过中介者来进行间接通信。这样,不仅降低了对象之间的依赖关系,还简化了对象之间的交互逻辑。

 

二、中介者模式的结构

        中介者模式通常包含以下几个关键角色:

  1. 抽象中介者(Mediator):定义一个接口,该接口用于定义各同事(Colleague)对象之间进行通信需要的方法。
  2. 具体中介者(ConcreteMediator):实现抽象中介者接口,通过协调各个同事对象来实现协作行为,了解并维护它的各个同事,它维持了对各个同事对象的引用。
  3. 抽象同事类(Colleague):定义各个同事类公有的方法,并声明了一些抽象方法来供子类实现,同时它维持了一个对抽象中介者类的引用,其子类可以通过该引用来与中介者通信。
  4. 具体同事类(ConcreteColleague):实现抽象同事类,每一个同事对象在需要和其他同事对象通信时,先与中介者通信,通过中介者来间接完成与其他同事类的通信。

三、中介者模式的理解

  1. 降低耦合度:通过引入中介者对象,各个对象之间的直接依赖关系被减少,使得系统结构更加灵活和可扩展。
  2. 简化交互:中介者模式将对象之间的多对多交互关系转换为中介者与各个对象之间的一对多关系,简化了对象之间的交互逻辑。
  3. 易于维护和扩展:由于对象之间的交互被集中到中介者对象中,因此当需要修改或扩展对象之间的交互时,只需修改中介者对象,而不需要修改各个对象的代码。

        然而,中介者模式也有其局限性。如果系统中存在大量的同事类,中介者可能会变得非常复杂,难以维护。因此,在实际应用中需要权衡利弊,根据具体情况决定是否采用该模式。

四、中介者模式的实践

        下面我们通过具体的Java代码示例来展示中介者模式的实践应用。

示例一:简单的聊天系统

        假设我们要设计一个可以让多人参与进去的聊天室,该聊天室需要实现发送消息和新增用户的功能。

        首先,我们定义聊天室的接口ChatRoom,其中包含两个方法sendMessageaddUser,分别代表发送消息和新增用户。这里的ChatRoom就是抽象的中介者类。

public interface ChatRoom {
    void sendMessage(String msg, String userId);
    void addUser(User user);
}


        然后,我们创建一个ChatRoom的实现类ChatRoomImpl,使用addUser来添加需要聊天的用户对象,同时这里再使用一个Map来保存添加时需要用来进行通信的对象列表。在发送消息sendMessage的方法中,我们通过userId指定某个对象来接收消息。

import java.util.HashMap;
import java.util.Map;

public class ChatRoomImpl implements ChatRoom {
    private Map<String, User> usersMap = new HashMap<>();

    @Override
    public void sendMessage(String msg, String userId) {
        User u = usersMap.get(userId);
        u.receive(msg);
    }

    @Override
    public void addUser(User user) {
        this.usersMap.put(user.getId(), user);
    }
}


        接下来,我们定义一个抽象组件类User,它持有一个ChatRoom的引用,并声明了发送消息send和接收消息receive的抽象方法。

public abstract class User {
    private ChatRoom mediator;
    private String id;
    private String name;

    public User(ChatRoom room, String id, String name) {
        this.mediator = room;
        this.name = name;
        this.id = id;
    }

    public abstract void send(String msg, String userId);

    public abstract void receive(String msg);

    public ChatRoom getMediator() {
        return mediator;
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}


        然后,我们实现一个具体的组件类ChatUser,并实现发送消息send和接收消息receive的方法。

public class ChatUser extends User {

    public ChatUser(ChatRoom room, String id, String name) {
        super(room, id, name);
    }

    @Override
    public void send(String msg, String userId) {
        getMediator().sendMessage(msg, userId);
    }

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


        最后,我们在客户端代码中创建中介者和同事对象的实例,并将它们关联起来。

public class ChatDemo {
    public static void main(String[] args) {
        ChatRoom chatRoom = new ChatRoomImpl();
        User user1 = new ChatUser(chatRoom, "1", "张三");
        User user2 = new ChatUser(chatRoom, "2", "李四");

        chatRoom.addUser(user1);
        chatRoom.addUser(user2);

        user1.send("你好, 李四", "2");
        user2.send("你好, 张三", "1");
    }
}


        运行上述代码,输出结果如下:

李四收到消息: 你好, 李四
张三收到消息: 你好, 张三


        通过这个示例,我们可以看到,聊天系统中的用户对象(User)通过中介者(ChatRoom)来进行间接通信,而不需要直接引用对方。这样,不仅降低了用户对象之间的耦合度,还简化了用户之间的交互逻辑。

示例二:多架飞机降落

        假设有多架飞机需要跑道降落,塔台作为中介者指挥飞机降落。每一架飞机都是一个组件,拥有一些相同的行为,塔台作为中介者负责指挥飞机的降落。

        首先,我们定义抽象中介者接口TowerMediator,它包含通知方法notify、注册方法register和移除方法remove

public interface TowerMediator {
    void notify(String type, String track);
    void register(AirplaneComponent colleague);
    void remove(AirplaneComponent colleague);
}


        然后,我们实现具体的中介者类AirlinerConcreteMediator,它持有一个List来管理组件对象(即飞机)。

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

public class AirlinerConcreteMediator implements TowerMediator {
    private List<AirplaneComponent> colleagues = new ArrayList<>();

    @Override
    public void notify(String type, String track) {
        for (AirplaneComponent airplaneComponent : colleagues) {
            if (!type.equalsIgnoreCase(airplaneComponent.getAirplaneType())) {
                continue;
            }
            airplaneComponent.landing(track);
        }
    }

    @Override
    public void register(AirplaneComponent colleague) {
        colleagues.add(colleague);
    }

    @Override
    public void remove(AirplaneComponent colleague) {
        colleagues.remove(colleague);
    }
}


        接下来,我们定义抽象组件类AirplaneComponent,它持有一个中介者对象的引用,并声明了一个抽象方法landing

public abstract class AirplaneComponent {
    public String airplaneType;
    private TowerMediator towerMediator;

    public AirplaneComponent(String airplaneType, TowerMediator towerMediator) {
        this.airplaneType = airplaneType;
        this.towerMediator = towerMediator;
    }

    public abstract void landing(String track);

    public TowerMediator getTowerMediator() {
        return towerMediator;
    }
}


        然后,我们实现具体的组件类AirlinerConcreteComponent,它代表客机。

public class AirlinerConcreteComponent extends AirplaneComponent {

    public AirlinerConcreteComponent(String airplaneType, TowerMediator towerMediator) {
        super(airplaneType, towerMediator);
    }

    @Override
    public void landing(String track) {
        System.out.println(airplaneType + "正在跑道" + track + "上降落");
    }
}


        最后,我们在客户端代码中创建中介者和组件对象的实例,并将它们关联起来。

// 客户端代码
public class AirportDemo {
    public static void main(String[] args) {
        // 创建中介者(塔台)
        TowerMediator towerMediator = new AirlinerConcreteMediator();
 
        // 创建具体的组件(飞机),并注册到中介者
        AirplaneComponent airplane1 = new AirlinerConcreteComponent("波音737", towerMediator);
        AirplaneComponent airplane2 = new AirlinerConcreteComponent("空客A320", towerMediator);
        AirplaneComponent airplane3 = new AirlinerConcreteComponent("波音787", towerMediator);
 
        // 通知中介者进行降落安排(这里假设有两个跑道:Runway 1 和 Runway 2)
        towerMediator.notify("波音737", "Runway 1");
        towerMediator.notify("空客A320", "Runway 2");
        towerMediator.notify("波音787", "Runway 1"); // 假设波音787可以等待或使用另一个空闲跑道
 
        // 注意:由于中介者内部已经维护了组件的列表,因此不需要显式地移除组件,
        // 除非在程序的某个阶段需要动态地卸载组件。
    }
}

        在这个示例中,AirportDemo类的main方法是客户端代码,它创建了中介者AirlinerConcreteMediator的实例,并创建了多个具体的组件(飞机)实例,这些实例都被注册到了中介者中。然后,通过调用中介者的notify方法,模拟了飞机请求降落的过程,并分配了跑道。

        运行AirportDemo类的main方法,您将看到类似以下的输出:

波音737 正在跑道 Runway 1 上降落
空客A320 正在跑道 Runway 2 上降落
波音787 正在跑道 Runway 1 上降落

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

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

相关文章

吸烟抽烟行为识别数据集-超高识别率,支持YOLO,COCO,VOC格式的标注,10162张各种姿势场景下的吸烟图片

吸烟抽烟行为识别数据集-超高识别率&#xff0c;支持YOLO&#xff0c;COCO,VOC格式的标注&#xff0c;10162张各种姿势场景下的吸烟图片 数据集分割 训练组91&#xff05; 9279图片 有效集5&#xff05; 507图片 测试集4% 376图片 预处理 自动定…

【开源】基于SpringBoot框架的房屋租赁系统 (计算机毕业设计)+万字毕业论文 T020

系统合集跳转 源码获取链接 一、系统环境 运行环境: 最好是java jdk 1.8&#xff0c;我们在这个平台上运行的。其他版本理论上也可以。 IDE环境&#xff1a; Eclipse,Myeclipse,IDEA或者Spring Tool Suite都可以 tomcat环境&#xff1a; Tomcat 7.x,8.x,9.x版本均可 操作系统…

C++20 标准概念

1. 所有标准概念的概述 “类型和对象基本概念”表列出了类型和对象的基本概念。 “范围、迭代器和算法概念”表列出了范围、视图、迭代器和算法的概念。 “辅助概念”表列出的概念主要用作其他概念的构建块&#xff0c;通常不会让应用程序开发者直接使用。 头文件和命名空间 …

git的卸载与安装

目录 一、Git的卸载 二、Git的安装 2.1.1 官网下载 2.1.2 镜像下载 ​编辑 2.2 安装 2.3 检验否安装成功 三、Git使用配置 一、Git的卸载 1.找到程序&#xff0c;卸载程序 2.找到Git&#xff0c;右键卸载 卸载完成&#xff01; 二、Git的安装 2.1.1 官网下载 网址&…

科技赋能电影,互动电影开启电影新格局

近年来&#xff0c;科技赋能电影&#xff0c;让电影越来越精彩&#xff0c;也越来越多元。层出不穷的新技术新类型&#xff0c;不断丰富着电影视听语言的表现形式&#xff0c;也为观众带来更多具有交互性和个性化的观影体验。进昂互动科技在推出全球首部院线互动电影《夜班》之…

python 下载 b站视频 和音频

video_bvid&#xff1a; import os import requests import json import re from bs4 import BeautifulSoup import subprocess # from detail_video import video_bvid# video_bvid 是一个从外部得到的单个视频ID video_bvid BV1cx421Q7veclass BilibiliVideoAudio:def __in…

操作系统:虚拟存储系统

目录 1、外存资源管理 外存空间划分 进程与外存对应关系 2、虚拟页式存储系统 3、 淘汰算法&#xff08;重点&#xff09;P217 最佳淘汰算法&#xff08;OPT&#xff09; 先进先出(FIFO) 最近最少使用算法&#xff08;LRU&#xff09; 最近不用的先淘汰(LNU) 最不经常…

Linux24.04 安装企业微信

今天工作需要把windows系统换成了linux&#xff0c;但是公司的沟通工具是企业微信。去企业微信官网看了&#xff0c;没有linux版本&#xff0c;只能想办法解决了&#xff0c;不然再换回去就太坑了。 方案 1、使用docker容器&#xff0c;2、使用deepin-wine 本人对docker不太熟…

手机实时提取SIM卡打电话的信令声音--社会价值(一、方案解决了什么问题)

手机实时提取SIM卡打电话的信令声音 --社会价值(一、方案解决了什么问题) 一、前言 这段时间&#xff0c;我们在技术范围之外陷入了一个自证或者说下定义的怪圈&#xff0c;即要怎么样去介绍或者描述&#xff1a;我们是一个什么样的产品。它在当前这个世界上&#xff0c;处于…

UnityShaderLab 实现黑白着色器效果

实现思路&#xff1a;取屏幕像素的RGB值&#xff0c;将三个通道的值相加&#xff0c;除以一个大于值使颜色值在0-1内&#xff0c;再乘上一个强度值调节黑白强度。 在URP中实现需要开启Opaque Texture ShaderGraph实现&#xff1a; ShaderLab实现&#xff1a; Shader "Bl…

Burp suite2 (泷羽sec)

声明 学习视频来自B站UP主 泷羽sec,如涉及侵泷羽sec权马上删除文章。 笔记只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 这节课旨在扩大自己在网络安全方面的知识面&#xff0c;了解网络安全领域的见闻&#xff0c;了…

Devops-蓝鲸篇-01-蓝鲸智云简介

官方社区 蓝鲸智云学习社区&#xff1a;https://bk.tencent.com/s-mart/communities 蓝鲸简介 腾讯蓝鲸智云&#xff0c;简称蓝鲸&#xff0c;是腾讯互动娱乐事业群&#xff08;Interactive Entertainment Group&#xff0c;简称 IEG&#xff09;基于海量异构业务自研的一套…

9. 高效利用Excel设置归档Tag

高效利用Excel设置归档Tag 1. Excle批量新建/修改归档Tag2. 趋势记录模型批量导入归档Tag(Method1)2. 趋势记录模型批量导入归档Tag(Method2)3. 趋势记录控件1. Excle批量新建/修改归档Tag Fcatory Talk常常需要归档模拟量,对于比较大的项目工程会有成千上万个重要数据需…

未来已来:人工智能如何重塑我们的生活与工作

引言 未来的生活和工作场景正从想象走向现实。想象一下&#xff0c;一个清晨&#xff0c;语音助手已经为你安排好一天的任务&#xff0c;自动驾驶汽车准时送你上班&#xff0c;智能冰箱提醒你需要补充的食材。曾经只存在于科幻小说中的场景&#xff0c;如今正在我们的身边实现。…

Ai编程从零开始部署Node项目接口开发之云服务器ECS安装部署mysql(十四)

云风网 云风笔记 云风知识库 为了体验基本的增删改查功能&#xff0c;用户注册/登录/用户列表查询展示/删除用户等接口开发是必要的&#xff0c;这里采用node项目开发部署。如果想要简便&#xff0c;可以采用宝塔运维面板。这里直接官网下载安装包部署云服务器 一、mysql官网下…

jmeter调整字号无法生效?

调整之前如上图&#xff0c;字体非常小&#xff0c;哪怕我设置的字号是48 查阅了资料&#xff0c;试了几次&#xff0c;解决办法如下&#xff1a; 用编辑器打开jmeter.bat 在echo off的下一行添加以下代码 set JVM_ARGS%JVM_ARGS% -Dswing.plaf.metal.controlFontDialog-20…

使用 mkcert 工具自签发 https 证书并进行本地受信

介绍 mkcert 是一个用于创建本地受信任的 SSL/TLS 证书的简单工具&#xff0c;特别适合开发者在本地环境中使用。它解决了为开发和测试目的创建自签名证书时遇到的信任问题。以下是关于 mkcert 的详细介绍&#xff1a; 特点 易用性&#xff1a;只需一条命令即可生成证书&…

视频推拉流EasyDSS无人机直播技术巡查焚烧、烟火情况

焚烧作为一种常见的废弃物处理方式&#xff0c;往往会对环境造成严重污染。因此&#xff0c;减少焚烧、推广绿色能源和循环经济成为重要措施。通过加强森林防灭火队伍能力建设与长效机制建立&#xff0c;各地努力减少因焚烧引发的森林火灾&#xff0c;保护生态环境。 巡察烟火…

C语言:分支结构

C语言&#xff1a;分支结构 分支结构 问题引出 我们在程序设计往往会遇到如下的问题&#xff0c;比如下面的函数的计算 也就是我们是必须要通过一个条件的结果来选择下一步的操作&#xff0c;算法上属于一个分支结构&#xff0c;C语言中实现分支结构主要使用if语句 条件判断…

图像矫正小白指南:从理论到实践的简单实现

一、引言 在日常生活中&#xff0c;使用手机拍全景照片或通过车载摄像头查看倒车影像时&#xff0c;常常会发现画面出现一定程度的变形。例如&#xff0c;建筑物的直线会被拉弯&#xff0c;或者车身轮廓显得不自然。这种现象就是图像畸变&#xff0c;它可能影响美观&#xff0…