Go设计模式--中介者,最后的模式!

news2025/1/16 6:39:51

大家好,这里是每周都在陪你一起进步的网管~!今天继续学习设计模式,也是我们要学习的最后一个设计模式—中介者模式,对这个模式有一点了解后会觉得它跟我们已经学过的观察者模式挺像,但是两者还是有些区别的,使用场景也不一样,具体我们放在最后再讲,先来一起学习中介者模式。

中介者模式是一种行为设计模式, 能让程序减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行交互。b665e327e270f147ec92fca1933f806d.png中介者模式使修改、扩展和重用单个组件变得容易,因为它们不再依赖于所有其他类。下面我们举一个简单的例子来说明怎么在程序里使用中介者模式减少各个组件类之间的耦合。

在现实生活中,机场的控制塔是一个典型的中介者角色, 飞机在起飞和降落前都会向控制塔发出问询,控制塔会给飞机发送指令协调它们的起飞降落时间,避免造成事故。

现在假设一个机场只有一条跑道,即同一时刻只能承载一架飞机的起飞和降落,飞机和飞机之间不能直接沟通,这样就乱套了,必须由控制塔作为一个中介者向各个飞机(组件)同步跑道的可用状态。1b603850d263acffb10b47d370ceb316.png下面我们先来定义飞机和指挥塔--即组件和中介者的 Interface 接口。

"本文使用的完整可运行源码
去公众号「网管叨bi叨」发送【设计模式】即可领取"
// 中介者--机场指挥塔的接口定义
type mediator interface {
 canLanding(airplane airplane) bool
 notifyAboutDeparture()
}

// 组件--飞行器的接口定义
type airplane interface {
 landing()
 takeOff()
 permitLanding()
}

接下来我们来实现具体的组件,这里提供两个组件作为演示,一架波音飞机和一架空客飞机。

每个飞机在降落landing方法里都会去跟作为中介者的指挥塔发出问询,看是否能够降落,如果跑道正在被占用,那么会等待指挥塔调用它自己的permitLanding()通知可以降落后再降落。而其他占用跑道的飞机在起飞后会通过中介者提供的notifyAboutDeparture() 告知指挥塔自己的离去。

具体的代码如下:

"本文使用的完整可运行源码
去公众号「网管叨bi叨」发送【设计模式】即可领取"
// 组件1--波音飞机
type boeingPlane struct {
 mediator
}

func (b *boeingPlane) landing() {
 if !b.mediator.canLanding(b) {
  fmt.Println("Airplane Boeing: 飞机跑到正在被占用,无法降落!")
  return
 }
 fmt.Println("Airplane Boeing: 已成功降落!")
}

func (b *boeingPlane)takeOff() {
 fmt.Println("Airplane Boeing: 正在起飞离开跑道!")
 b.mediator.notifyAboutDeparture()
}

func (b *boeingPlane)permitLanding() {
 fmt.Println("Airplane Boeing: 收到指挥塔信号,允许降落,正在降落!")
 b.landing()

}

// 组件2--空客飞机
type airBusPlane struct {
 mediator mediator
}

func (airbus *airBusPlane) landing() {
 if !airbus.mediator.canLanding(airbus) {
  fmt.Println("Airplane AirBus: 飞机跑到正在被占用,无法降落!")
  return
 }
 fmt.Println("Airplane AirBus: 已成功降落!")
}

func (airbus *airBusPlane) takeOff() {
 fmt.Println("Airplane AirBus: 正在起飞离开跑道!")
 airbus.mediator.notifyAboutDeparture()
}

func (airbus *airBusPlane)permitLanding() {
 fmt.Println("Airplane AirBus: 收到指挥塔信号,允许降落,正在降落!")
 airbus.landing()
}

作为中介者的指挥塔,提供两个方法

  • canLanding:提供给飞机组件问询是否可以降落的方法,如果不可以会把飞机加入到等待队列中,后续跑道空闲后会进行通知。

  • notifyAboutDeparture:提供给占用跑道的飞机通知指挥塔已起飞,指挥塔会向排队降落的飞机中的首位发送降落指令--调用飞机对象的permitLanding方法

"本文使用的完整可运行源码
去公众号「网管叨bi叨」发送【设计模式】即可领取"
// 中介者实现--指挥塔
type manageTower struct {
 isRunwayFree bool
 airportQueue []airplane
}

func (tower *manageTower) canLanding(airplane airplane) bool {
 if tower.isRunwayFree {
  // 跑道空闲,允许降落,同时把状态变为繁忙
  tower.isRunwayFree = false
  return true
 }
 // 跑道繁忙,把飞机加入等待通知的队列
 tower.airportQueue = append(tower.airportQueue, airplane)
 return false
}

func (tower *manageTower) notifyAboutDeparture() {
 if !tower.isRunwayFree {
  tower.isRunwayFree = true
 }
 if len(tower.airportQueue) > 0 {
  firstPlaneInWaitingQueue := tower.airportQueue[0]
  tower.airportQueue = tower.airportQueue[1:]
  firstPlaneInWaitingQueue.permitLanding()
 }
}

func newManageTower() *manageTower {
 return &manageTower{
  isRunwayFree: true,
 }
}

这样我们就可以通过指挥塔,协调多个飞机使用飞机场跑道进行有序的起飞和降落了。

"本文使用的完整可运行源码
去公众号「网管叨bi叨」发送【设计模式】即可领取"
func main() {
 tower := newManageTower()
 boeing := &boeingPlane{
  mediator: tower,
 }
 airbus := &airBusPlane{
  mediator: tower,
 }
 boeing.landing()
 airbus.landing()
 boeing.takeOff()
}

执行程序后,会有类似下面的输出:

c39c171101197745fa0708bd751f06c2.png

本文的完整源码,已经同步收录到我整理的电子教程里啦,可向我的公众号「网管叨bi叨」发送关键字【设计模式】领取。

fee24c68166df237583a7ffd681b64c9.png
公众号「网管叨bi叨」发送关键字【设计模式】领取。

看完例子对中介者模式有了一定了解后我们接下来再详细说说它的构成以及用代码实现中介者模式的步骤。

中介者模式的构成

中介者模式的结构构成可以用下面的UML类图来表示be1eb22cb596a9787e9ade7b9fd13a98.png图中的各个类的构成跟我们上面代码实例中列举的十分类似,Component 实现类里需要持有指向中介者的引用,中介者里也保有对各个组件对象的引用,只不过示例里是把组件保存在一个列表里,UML 中是把各个组件单独保存在了中介者的属性里。

下面我们再把用代码实现中介者模式的步骤简单叙述一遍:

  1. 定义一组会相互调用,拥有强耦合的组件。

  2. 指定中介者接口以及中介者与各个组件之间的通信方式。在大多数情况下中介者接口中必须有一个Notify/Notification方法从组件接收通知。

  3. 创建具体中介者实现,该实现将会存储其管理的所有Component对象的引用

  4. 组件对象应该保存中介者的引用,如果想在不同上下文下使用不同的中介者实现,那么应该通过中介者接口类型保存对具体中介者的引用。

  5. 将组件对象调用其他组件对象的方法提炼到中介者中,组件对象调用中介者的通知方法,由中介者再去调用相对应的组件的方法,从而完成组件与组件间的解耦。

中介模式与观察者模式区别

中介模式与观察者模式在结构上有些相似,观察者模式中的EventDispatcher 和 中介模式中的 Mediator 看起来很想,都是把多个组件之间的关系,维护到自身,实现组件间的间接通信达到解构效果,不过这两个设计模式在使用场景或者叫要解决的问题上,还是有些差别

  • 观察者模式

    • 组件间的沟通是单向的,从被观察(发送事件的实体)到观察者(监听器),一个参与者要么是观察者要么是被观察者,不会同时兼具两种身份。

  • 中介模式

    • 参与者之间可以双向沟通,当参与者之间关系复杂维护成本很高的时候可以考虑中介模式。

总结

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

中介者模式主要适用于以下应用场景。

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

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

中介者模式的优点

  • 减少类间依赖,将多对多依赖转化成一对多,降低了类间耦合。

  • 类间各司其职,符合迪米特法则。

中介者模式的缺点

  • 中介者模式将原本多个对象直接的相互依赖变成了中介者和多个组件类的依赖关系。

  • 当组件类越多时,中介者就会越臃肿,变得复杂且难以维护。

最后

今天这篇完结后,用Go学设计模式就正式更新完了,算是一个小小的成就,大家可以在专辑链接里查看系列里的其他文章,后面会写篇总结把设计模式的学习心法给大家说一说,其实就是多看,多练,除此之外也有点小技巧,咱们放到后面给系列收尾时再说。

大家可以期待一下,没有关注的记得给个关注。

- END -

扫码关注公众号「网管叨bi叨」

给网管个星标,第一时间吸我的知识 👆

网管整理了一本《Go 开发参考书》收集了70多条开发实践。去公众号回复【gocookbook】领取!还有一本《k8s 入门实践》讲解了常用软件在K8s上的部署过程,公众号回复【k8s】即可领取!

觉得有用就点个在看  👇👇👇

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

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

相关文章

chatgpt赋能Python-python_entry如何清空

Python Entry如何清空 Python是一种高级编程语言,因其简单易学、代码优美而被广泛应用于数据科学、机器学习、Web开发等领域。在Python中,Entry是常用的GUI元素之一,用于接受用户输入。但有时候需要清空Entry中的文本,本文将介绍…

python中字符串的类型转换

一、使用eval----含有{}字符串的转换为list、tuple、dict- eval():将字符串str当成有效的表达式来求值并返回计算结果 (1)字符串转换为列表 (2)字符串转换为元组 a " ([1,3],[1,2],[1,1])…

STM8 调试红外遥控器HS003B

背景 项目中使用STM8S003F3P6,控制红外遥控器HS003B,调试过程也遇到了很多问题,这里做个记录。 问题1:长按按键问题,如果长按遥控的某个按键,应该是一直能响应该按键值(需要对接收状态、接收信…

工作模式(3)

8bit PWM PWM模式开启时,计数器与比较寄存器连续比较,当计数值小于比较寄存器,输出为低,当计数值大于等于比较寄存器,输出为高,并且保持到计数值等于重载寄存器,然后计数器回到0开始重新计数&am…

【三维激光扫描】实验05:点云数据预处理操作

SiScan软件可以对三维激光扫描的点云数据进行一些列的预处理操作,如:粗差剔除、点云抽稀、点云分割、调整水平面、删除分割面等等。 粗差剔除剔除粗差点抽稀抽稀数据点云分割根据点云的三维特征进行分组调整水平面根据三个点来调整水平面分割面水平纠正根据分割面进行水平纠正…

小心你的 OpenAI Key 被盗!

公众号关注 “GitHubDaily” 设为 “星标”,每天带你逛 GitHub! 今年随着 ChatGPT 发布,其强悍的能力也让 GPT-3.5/4 成为炙手可热的大语言模型,使得不少 AI 应用接入了 OpenAI 接口。当用户使用这些应用时,经常需要填…

Python自动化办公对每个子文件夹的Excel表加个表头(Excel不同名)(上篇)

点击上方“Python爬虫与数据挖掘”,进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 含情凝睇谢君王,一别音容两渺茫。 大家好,我是皮皮。 一、前言 上一篇文章,我们抛出了一个问题,这篇文章…

工作模式(2)

输入捕捉 输入捕捉功能的主要特点: ⚫ 上升沿或下降沿捕捉 ⚫ 脉冲宽度捕捉或脉冲周期捕捉 ⚫ 带清零的捕捉或自由计数捕捉 ⚫ 单次捕捉或连续捕捉 捕捉模式只能工作在16bit级联模式下,从0开始计数。当选择上升沿捕捉周期模式时,电路在检测到…

chatgpt赋能Python-python_fetchone

Python fetchone方法简介 在Python编程领域中,fetchone()是一个经常使用的方法。fetchone()方法用于从数据库中获取单个结果,并将结果存储在变量中。本文将介绍fetchone()方法的详细信息,并探讨如何在Python中使用该方法。 什么是fetchone方…

chatgpt赋能Python-python_chariot

Python Chariot:一款强大的Python IDE Python Chariot是一款强大的Python IDE,它的特点是简单易用,功能齐全。该IDE适用于各种Python编程任务,无论是编写小型脚本还是大型项目。在本文中,我们将深入介绍Python Chario…

Windows本地快速搭建SFTP服务共享文件 - 外网访问【端口映射】

文章目录 1. 搭建SFTP服务器1.1 下载 freesshd服务器软件1.3 启动SFTP服务1.4 添加用户1.5 保存所有配置 2 安装SFTP客户端FileZilla测试2.1 配置一个本地SFTP站点2.2 内网连接测试成功 3 使用cpolar内网穿透3.1 创建SFTP隧道3.2 查看在线隧道列表 4. 使用SFTP客户端&#xff0…

基于SpringBoot的停车位智能管理系统的设计与实现_kaic

摘 要 随着经济与交通事业的飞速发展,汽车的保有量呈现上升趋势,公共停车位 智能化在信息时代显得尤为重要。面对有限的公共停车位与上升的汽车保有量, 通过合理利用公共停车位来提高车位的利用率是大势所趋。 基于上述背景,本论…

为生信写的Python简明教程 | 视频4

开源生信 Python教程 生信专用简明 Python 文字和视频教程 源码在:https://github.com/Tong-Chen/Bioinfo_course_python 目录 背景介绍 编程开篇为什么学习Python如何安装Python如何运行Python命令和脚本使用什么编辑器写Python脚本Python程序事例Python基本语法 数…

基于 Log 的通用增量 Checkpoint 在美团的进展

摘要:本文整理自美团计算引擎工程师王非凡,在 Flink Forward Asia 2022 核心技术专场的分享。本篇内容主要分为四个部分: 1. Log based Checkpoint 基本原理介绍 2. 美团应用场景及测试效果 3. Changelog Restore 性能优化 4. Changelog 存储…

49天精通Java,第35天,Java初始化、构造器、对象创建的过程

目录 一、初始化与清理二、用构造器保证初始化1、无参构造器2、有参构造器 三、成员初始化1、显式初始化2、隐式初始化3、初始化块 四、对象创建的过程 大家好,我是哪吒。 🏆本文收录于,49天精通Java从入门到就业。 全网最细Java零基础手把…

微服务开发系列 第三篇:OpenFeign

总概 A、技术栈 开发语言:Java 1.8数据库:MySQL、Redis、MongoDB、Elasticsearch微服务框架:Spring Cloud Alibaba微服务网关:Spring Cloud Gateway服务注册和配置中心:Nacos分布式事务:Seata链路追踪框架…

多维时序 | MATLAB实现GA-GRU遗传算法优化门控循环单元多变量时间序列预测

多维时序 | MATLAB实现GA-GRU遗传算法优化门控循环单元多变量时间序列预测 目录 多维时序 | MATLAB实现GA-GRU遗传算法优化门控循环单元多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 多维时序 | MATLAB实现GA-GRU遗传算法优化门控循环单元多变量时间…

OSPF 邻居关系 附实验

实验目的 通过对 OSPF 邻居关系建立进行相关的实验,从中学习到如何调整 OSPF Hello 包间隔,Dead 间隔,以及影响 OSPF 邻居建立的因素,例如 RID,MTU,OSPF 认证。并且将总结 OSPF在不同网络类型上的不同行为…

FPGA纯verilog实现CameraLink视频接收和发送,附带工程源码和技术支持

目录 1、前言2、CameraLink协议基础3、目前我已有的CameraLink收发工程4、设计方案5、CameraLink解码模块详解6、CameraLink编码模块详解7、vivado工程详解8、上板调试验证9、福利:工程代码的获取 1、前言 FPGA实现CameraLink视频编解码目前有两种方案:…

C++基本介绍

文章目录 🥭1.C基本介绍🧂1.1 C是什么🧂1.2 C发展史 🍒2. C的优势🥔2.1 语言的使用广泛度🥔2.2 C的应用领域 🫒3. C学习计划 🥭1.C基本介绍 🧂1.1 C是什么 C是一种通用…