C 嵌入式系统设计模式 10:中介者模式

本书的原著为:《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》,讲解的是嵌入式系统设计模式,是一本不可多得的好书。

本系列描述我对书中内容的理解。本文章描述访问硬件的设计模式之三:中介者模式。

中介者模式 (Mediator Pattern) 是一种设计模式,它在软件工程中用于减少类与类之间的直接依赖,降低系统的耦合度,使系统更加灵活和可扩展。该模式通过引入一个中介者对象,将原本需要直接交互的多个对象之间的关系转化为中介者与这些对象之间的关系,从而实现了解耦。

在本书中,中介者模式用于协调复杂交互,使得各个硬件接口不需要显示地相互引用,从而降低耦合度。

为了更好地理解中介者模式,我们可以将其比作现实生活中的房屋中介。在房屋租赁市场中,房东和租客之间通常需要直接进行交互以完成租赁交易。然而,当市场变得复杂时,这种直接交互可能会变得困难且效率低下。此时,房屋中介作为中介者出现,他们负责协调房东和租客之间的交互,处理租赁合同、租金支付等事务,从而简化了交互过程。

在软件工程中,中介者模式同样扮演着类似的角色。例如,在一个图形用户界面(GUI)系统中,多个组件(如按钮、文本框等)之间可能需要进行复杂的交互。如果每个组件都直接与其他组件进行交互,那么系统的耦合度将会非常高,一旦某个组件发生变化,可能会影响到其他多个组件。此时,可以引入一个中介者对象(如事件处理器)来管理这些组件之间的交互。当某个组件需要与其他组件进行交互时,它只需将请求发送给中介者对象,由中介者对象负责协调和处理这些请求。

中介者模式的核心在于将原本复杂的对象间关系转化为简单的中介者与对象间的关系。这种转化不仅降低了系统的耦合度,还提高了系统的可维护性和可扩展性。当需要添加新的交互关系或修改现有交互关系时,只需修改中介者对象即可,而无需修改其他多个对象。

然而,中介者模式也存在一些潜在的问题。例如,如果中介者对象变得过于复杂和庞大,那么它可能会成为系统中的瓶颈。此外,如果系统中存在多个中介者对象,它们之间可能需要进行协调和管理,否则可能会导致系统变得混乱和难以维护。

摘要

通过引入一个中介者对象来封装硬件元素之间交互的复杂性,中介者模式允许硬件元素之间更松散的耦合,提高了代码的可维护性和可扩展性。在C语言中,由于没有直接支持面向对象编程的特性,如类和继承,因此使用中介者模式可以避免因过度使用特殊化而导致的实现复杂性增加。相反,中介者模式可以通过结构体和函数指针等C语言特性来实现,从而简化对硬件元素的管理和协调。

问题

许多嵌入式应用控制一组执行器,这些执行器必须协同工作才能实现预期的效果。例如,为了实现多关节机械臂的协调运动,所有电机必须协同工作以提供所需的机械臂运动。类似地,在三维空间中使用航天器的反作用轮或推进器时,需要许多不同的此类设备,它们要在精确的时刻、提供适当的作用力,才能实现姿态稳定。

在这种情况下,中介者模式可以用来管理这些执行器之间的复杂交互。中介者可以作为一个集中的控制点,接收来自应用程序的指令,并根据需要协调各个执行器的行为。这样可以将执行器之间的直接交互降到最低,使得系统更加模块化和可维护。同时,通过使用中介者模式,我们可以更容易地添加、修改或删除执行器,而不需要对整个系统进行大规模的修改。

模式结构

模式结构图如下图所示:
在这里插入图片描述

中介者模式使用一个中介者类来协调一组协作设备的 动作 (actions),以实现所需的整体效果。中介者类协调对多个具体协作者(Specific Collaborator)集合的控制(它们的数量由图3-5中中介者和具体协作者之间的关联上的’*'表示)。当发生感兴趣的事件时,每个具体协作者必须能够联系中介者。

在这种模式中,中介者充当了中央控制器的角色,负责接收和处理来自各个协作者的消息,并根据需要协调它们的行为。这样可以将协作者之间的直接依赖关系降到最低,提高了系统的可维护性和可扩展性。同时,由于中介者负责协调和控制整个系统的行为,因此可以更容易地实现复杂的交互和协作逻辑。

模式详情

协作者接口

协作者接口(Collaborator Interface)是所有具体协作者共有的一组服务的规范,这些服务可以被中介者调用。例如,对于所有硬件设备来说,通常会有 initialize() 、reset()、shutdown() 等操作,以便将它们都带到一个已知的初始状态、恢复状态、关闭状态。每个通用服务必须在每个具体协作者中实现(当然,实现通常对每个协作者来说是唯一的)。

通过使用协作者接口,我们可以确保中介者能够与所有具体协作者以一致的方式进行交互,而无需关心它们的具体实现细节。这有助于降低系统的复杂性,并提高代码的可维护性和可扩展性。同时,这也为添加新的具体协作者提供了灵活性,因为只要它们实现了协作者接口,就可以与中介者进行交互。

具体协作者

具体协作者(Specific Collaborator)代表一个设备,因此可能是一个设备驱动程序或硬件代理。它接收中介者的命令消息,并在发生感兴趣的事件时向中介者发送消息。

在中介者模式中,具体协作者通常负责处理与具体设备相关的具体操作和事件。它们与中介者进行交互,通过接收中介者的命令来执行相应的操作,并在必要时向中介者发送事件消息以通知其状态变化或其他重要事件的发生。

通过将设备逻辑封装在具体协作者中,中介者模式实现了设备与系统其他部分之间的解耦。这使得系统更加模块化,易于维护和扩展。同时,具体协作者的设计也使得对设备的控制和管理更加集中和统一,提高了系统的整体效率和可靠性。

中介者

中介者 类(Mediator)在模式中协调 具体协作者 。它与每个具体协作者都有关联,以便可以向其发送消息。此外,当发生感兴趣的事件时,每个具体协作者必须能够向中介者发送消息。中介者提供了协调逻辑,避免了具体协作者之间相互协调。

通过引入中介者,我们可以将原本分散在具体协作者之间的交互和依赖关系集中到中介者身上,从而降低了系统的复杂性。中介者负责管理和维护具体协作者之间的关系,确保它们按照预定的规则和顺序进行交互。这样,具体协作者之间不再需要直接相互引用和调用,而是通过中介者来进行间接的交互,提高了系统的灵活性和可维护性。

同时,中介者模式也使得我们可以更容易地添加、删除或替换具体协作者,而不需要对整个系统进行大规模的修改。因为中介者封装了与具体协作者的交互逻辑,所以当我们需要改变某个具体协作者的行为时,只需要修改中介者与该协作者的交互逻辑即可,而不需要修改其他具体协作者或整个系统的代码。这大大提高了系统的可扩展性和可维护性。

效果

此模式创建了一个中介者,用于协调一组协作执行器,但不需要这些设备之间的直接耦合。通过最小化耦合点并将协调逻辑封装在单个元素内,这大大简化了整体设计。每当协作者需要联系另一个协作者时,它会通知中介者,中介者可以决定如何作为一个整体的协作体进行响应。

由于许多嵌入式系统必须实时控制,因此动作之间的延迟可能会导致不稳定或不良的影响。中介者类能够在这些时间限制内作出反应是非常重要的。当执行器与中介者之间存在双向协作时,这一点尤其令人关注。

实现策略

中介者必须能够与每个具体协作者建立关联。这可以通过指针数组、为每个具体协作者设置单独的指针,或者将两者组合起来实现。一个常见的经验法则是,如果一组具体协作者具有相同的行为(例如,它们遵循一个通用接口),那么指针数组是最佳选择。如果具体协作者有不同的用途,则为每个这样的具体协作者使用单独的链接。

甚至可以将不同的具体协作者分组,其中组内的每个类都提供一个通用接口。这样,中介者可以更容易地管理和协调具有相似功能或特性的协作者集合。

相关模式

此模式与经典《设计模式》书籍中的策略模式相似。在这种情况下,我们关注其在详细硬件协调方面的应用。

策略模式通常用于定义一系列的算法,并将每一个算法封装起来,使它们可以互相替换。策略模式使得算法可以独立于使用它的客户端变化。而在中介者模式中,我们同样看到了一种将行为或策略封装在中介者中的做法,这使得具体协作者之间的交互可以被中介者管理和协调。

在某些情况下,可以用观察者模式代替中介者模式。观察者模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。在中介者模式中,如果具体协作者需要与多个其他对象进行交互,或者我们不希望具体协作者直接知道中介者的存在,那么可以使用观察者模式来实现这种间接的交互。

实例

见原书

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

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

相关文章

【书籍分享 • 第三期】虚拟化与容器技术

文章目录 一、本书内容二、读者对象三、编辑推荐四、前言4.1 云计算技术的发展4.2 KVM、Docker4.3 本书内容简介4.4 作者简介 五、粉丝福利 一、本书内容 《虚拟化与容器技术》通过深入浅出的方式介绍KVM虚拟化技术与Docker容器技术的概念、原理及实现方法,内容包括…

备战蓝桥杯Day17 - 链表

链表 基本概念 链表是由一系列节点组成的元素集合。 每个节点包含两部分:数据域 item 、指向下一个节点的指针 next 通过节点之间的相互链接,形成一个链表 1. 链表的初始化 # 手动建立链表 # 链表的初始化 class Node(object):def __init__(self, …

ChatGPT带火的HBM是什么?

“ChatGPT是人工智能领域的iPhone时刻,也是计算领域有史以来最伟大的技术之一。” 英伟达创始人兼CEO黄仁勋此前这样盛赞ChatGPT。 ChatGPT突然爆火,对大算力芯片提出了更高更多的要求。近日,据韩国经济日报报道,受惠于ChatGPT&am…

易基因:CHH甲基化丢失可触发玉米表观等位基因的可遗传变化|作物研究

大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。 研究人员已经在多种植物物种中观察到在杂交过程中跨染色体间互作而导致DNA甲基化变化。然而,这些互作的原因或结果知之甚少。 2023年12月18日,佛罗里达大学微生物…

ClickHouse 指南(三)最佳实践 -- 主键稀疏索引

在ClickHouse主索引的实用介绍 ClickHouse release 24.1, 2024-01-30 1、简介 在本指南中,我们将深入研究ClickHouse索引。我们将详细说明和讨论: ClickHouse中的索引与传统的关系数据库管理系统有何不同ClickHouse是如何构建和使用表的稀疏主索引的什么是在Clic…

[c/c++] static 关键字

从修饰的对象来看,static 可以修饰局部变量,也可以修饰全局变量,可以修饰函数;可以修饰类中的成员变量以及成员函数。 从生命周期的角度来看,static 修饰的对象的生命周期,与进程的生命周期是一致的。 从…

YOLOv7代码解读[01] readme解读

模型性能 安装 # create the docker container, you can change the share memory size if you have more. nvidia-docker run --name yolov7 -it -v your_coco_path/:/coco/ -v your_code_path/:/yolov7 --shm-size64g nvcr.io/nvidia/pytorch:21.08-py3# apt install requir…

如果使用npm无法下载模块依赖,那么你可以尝试一下这个方法

问题复现 如果执行,npm install XXXX,出现了无法安装,一直等待,如何解决? 解决方法 1.先查看npm配置 npm config ls2.设置prefix和cache(可选) 指定到node安装目录 npm config set prefix …

【QT+QGIS跨平台编译】之五十一:【QGIS_CORE跨平台编译】—【qgsexpressionparser.cpp生成】

文章目录 一、Bison二、生成来源三、构建过程一、Bison GNU Bison 是一个通用的解析器生成器,它可以将注释的无上下文语法转换为使用 LALR (1) 解析表的确定性 LR 或广义 LR (GLR) 解析器。Bison 还可以生成 IELR (1) 或规范 LR (1) 解析表。一旦您熟练使用 Bison,您可以使用…

Netwalker勒索病毒服务私有化,只攻击目标企业

前言 2020年勒索病毒攻击出现了一些新的发展趋势,一些勒索病毒黑客组织将目标对准了一些国内外明星,网红博主等,还有一些勒索病毒黑客组织将自己的RAAS平台私有化,像之前比较流行的NEMTY勒索病毒黑客组织,就公开声称将…

LeetCode刷题--- 环形子数组的最大和

个人主页:元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 ​​​​​​http://t.csdnimg.cn/6AbpV 数据结构与算法 ​​​http://t.csdnimg.cn/hKh2l 前言:这个专栏主要讲述动…

Qt QWidget 简约美观的加载动画 第五季 - 小方块风格

给大家分享两个小方块风格的加载动画 &#x1f60a; 第五季来啦 &#x1f60a; 效果如下: 一个三个文件,可以直接编译运行 //main.cpp #include "LoadingAnimWidget.h" #include <QApplication> #include <QGridLayout> int main(int argc, char *arg…

vulnhub----hackme2-DHCP靶机

文章目录 一&#xff0c;信息收集1.网段探测2.端口扫描3.目录扫描 二&#xff0c;信息分析三&#xff0c;sql注入1.判断SQL注入2.查询显示位3.查询注入点4.查询库5.查询表6.查字段7. 查user表中的值8.登陆superadmin用户 四&#xff0c;漏洞利用文件上传命令执行蚁剑连接 五&am…

SwiftUI中的 WebView

SwiftUI中的WebView是一个用于显示网页内容的视图。它是使用WebKit框架的一个封装。 要在SwiftUI中使用WebView&#xff0c;你可以按照以下步骤操作&#xff1a; 首先&#xff0c;导入WebKit框架&#xff1a; import WebKit创建一个WebView实例&#xff1a; struct WebView…

将文件从windows传入到ubuntu

实现效果图 2.方法&#xff1a; 2.1打开 Ubuntu 的终端窗口&#xff0c;然后执行如下命令来安装 FTP 服务 输入&#xff1a;sudo apt-get install vsftpd 等待软件自动安装&#xff0c;安装完成以后使用如下 VI 命令打开/etc/vsftpd.conf&#xff0c;命令如下&#xff1a;su…

qt5.15 升级 qt 6.5 部分问题 解决修复

报错 QT5_USE_MODULES 升级 QT6_ADD_RESOURCES qt_add_resources Compiles binary resources into source code. CMake Commands in Qt6 Core | Qt Core 6.6.2

CrossOver24.0新功能介绍以及2024使用激活教程

CrossOver24简介 CrossOver 24.0 Mac/Linux版是一款功能强大的类虚拟机软件。CrossOver 24.0 for Mac/Linux软件能够帮助在Mac/Linux系统上使用Windows系统所支持的软件&#xff0c;实现各个系统之间的无缝集成。通过crossover 24.0软件用户可以进行跨平台的复制粘贴和文件互通…

刷题日记 | 字符串扩容和增强型for循环

for(char c:s)遍历字符串 增强型for循环 C for(char c:s)遍历字符串 增强型for循环_c for (char c : s)-CSDN博客 字符串使用前要进行扩容 reserve函数 【CString类成员函数辨析】resize(),size(),capacity(),reserve()函数的解析与对比_c reserve函数-CSDN博客 a.size() 用来…

ES小总结

组合查询 FunctionScoreQueryBuilder functionScoreQuery QueryBuilders.functionScoreQuery(boolQuery,new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("isAD",true),Score…

顺丰科技2024届春季校园招聘常见问题解答及SHL测评题库

顺丰科技2024届春季校园招聘常见问题解答及SHL测评题库 Q&#xff1a;顺丰科技2024届校园招聘面向对象是&#xff1f; A&#xff1a;2024届应届毕业生&#xff0c;毕业时间段为2023年10月1日至2024年9月30日&#xff08;不满足以上毕业时间的同学可以关注顺丰科技社会招聘或…