JavaScript设计模式(五)——发布订阅模式、桥接模式、组合模式
个人简介
👀个人主页: 前端杂货铺
🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒Three.js 🍖JS版算法
🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧
设计模式
| 内容 | 参考链接 |
|---|---|
| JavaScript设计模式(一) | 构造器模式、原型模式、类模式 |
| JavaScript设计模式(二) | 简单工厂模式、抽象工厂模式、建造者模式 |
| JavaScript设计模式(三) | 单例模式、装饰器模式、适配器模式 |
文章目录
- 设计模式
- ✨✨前言
- 一、发布订阅模式
- 二、桥接模式
- 三、组合模式
- 🎉🎉本篇小结
✨✨前言
大家好,这里是前端杂货铺。
上一节,我们学习了策略模式、代理模式、观察者模式。这一节,我们学习发布订阅模式、桥接模式和组合模式…
一、发布订阅模式
观察者和目标要互相知道,发布者和订阅者 不用相互知道,通过第三方实现调度,属于 经过解耦合的 观察者模式。
我们定义 PubSub 类(发布订阅),里面的 message 对象用于存放要订阅的信息。
subscribe 方法期待两个参数(type 和 cb),type 表示要订阅的类型,cb 表示订阅的详细信息,直接把 cb 赋值给 type 即可。
publish 方法也期待两个参数(type 和 data),如果发布的时候没有该类型,则直接 return,否则发布出该类型。
unsubscribe 同 subscribe 一样,期待两个参数,用于取消订阅。
class PubSub {message = {};// 发布publish(type, data) {// 发布的时候没有该类型,直接 returnif (!this.message[type]) return;this.message[type].forEach(item => item(data));}// 订阅subscribe(type, cb) {this.message[type] = [cb];}// 取消订阅unsubscribe(type, cb) {// 取消订阅的时候如果没有该类型,直接 returnif (!this.message[type]) return;if (!cb) {this.message[type] && (this.message[type].length = 0);} else {this.message[type] = this.message[type].filter(item => item !== cb);}}
}// 创建 pubsub 实例
const pubsub = new PubSub();function milk(data) {console.log('milk', data);
}function apple(data) {console.log('apple', data);
}function chicken(data) {console.log('chicken', data);
}// 订阅 牛奶、苹果、大盘鸡
pubsub.subscribe('milk', milk);
pubsub.subscribe('apple', apple);
pubsub.subscribe('chicken', chicken);// 发布 牛奶、苹果、大盘鸡
pubsub.publish('milk', '牛奶');
pubsub.publish('apple', '苹果');
pubsub.publish('chicken', '大盘鸡');console.log('分-----割-----线')// 取消对大盘鸡的订阅
pubsub.unsubscribe('chicken');// 发布 牛奶、苹果、大盘鸡(大盘鸡不会被发布,因为被取消订阅了)
pubsub.publish('milk', '牛奶');
pubsub.publish('apple', '苹果');
pubsub.publish('chicken', '大盘鸡');

二、桥接模式
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
使用场景:一个类存在两个或多个独立变化的维度,且这两个维度都需要进行扩展。
优点:把抽象与实现隔开,有助于独立地管理各组成部分。
缺点:每使用一个桥接元素都要增加一次函数调用,这对程序的性能会有一些负面影响,还提高了系统的复杂程度。
举个栗子:汽车厂商会把同一型号的发动机放到多款车型上使用。拿奥迪为例,假如它有 V6、V8 两款发动机,那么这两款发动机会装载到奥迪轿车或奥迪SUV两种车型中。

// 奥迪轿车(车型一)
class Aodi1 {constructor(engine) {this.engine = engine;}
}// 轿车平台
Aodi1.prototype.platform = function() {console.log('aodi1 轿车平台');
}// 加载轿车发动机
Aodi1.prototype.loadEngine = function() {this.engine.run();
}// 奥迪SUV(车型二)
class Aodi2 {constructor(engine) {this.engine = engine;}
}// SUV平台
Aodi2.prototype.platform = function() {console.log('aodi2 SUV平台');
}// 加载SUV发动机
Aodi2.prototype.loadEngine = function() {this.engine.run();
}// V6 发动机
function V6() {this.run = () => {console.log('v6发动机');}
}// V8 发动机
function V8() {this.run = () => {console.log('v8发动机');}
}// 搭载 V6 发动机的轿车
let car1 = new Aodi1(new V6());
// 搭载 V8 发动机的轿车
let car2 = new Aodi1(new V8());
// 搭载 V8 发动机的SUV
let suv1 = new Aodi2(new V8());car1.platform();
car1.loadEngine();car2.platform();
car2.loadEngine();suv1.platform();
suv1.loadEngine();

三、组合模式
组合模式在对象间形成 树形结构;
组合模式中基本对象和组合对象被一致对待;
无须关系对象有多少层,调用时只需在根部进行调用;
比如我们扫描文件夹和文件夹里面的文件,它是一种树形结构,我们从根文件夹出发,扫描二级文件夹,再扫描二级文件夹里的文件…,类似于如下结构:

// 文件夹
const Folder = function(folder) {this.folder = folder;this.list = [];
}// 添加文件夹
Folder.prototype.add = function(res) {this.list.push(res);
}// 扫描文件夹
Folder.prototype.scan = function() {console.log('扫描文件夹', this.folder);for (let i = 0; i < this.list.length; i++) {this.list[i].scan();}
}// 文件
const File = function(file) {this.file = file;
}// 扫描文件
File.prototype.scan = function() {console.log('开始扫描文件', this.file);
}// 根文件夹
let rootFolder = new Folder("root");// 子文件夹
let htmlFolder = new Folder("html");
let cssFolder = new Folder("css");
let jsFolder = new Folder("js");// 文件
let html4 = new File("html4");
let html5 = new File("html5");
let css2 = new File("css2");
let css3 = new File("css3");
let es5 = new File("es5");
let es6 = new File("es6");// 添加文件夹
rootFolder.add(htmlFolder);
rootFolder.add(cssFolder);
rootFolder.add(jsFolder);// 添加文件
htmlFolder.add(html4);
htmlFolder.add(html5);
cssFolder.add(css2);
cssFolder.add(css3);
jsFolder.add(es5);
jsFolder.add(es6);// 从根扫描
rootFolder.scan();

🎉🎉本篇小结
本文我们了解了发布订阅模式、桥接模式、组合模式。
发布订阅模式 的发布者和订阅者不用相互知道,通过第三方实现调度,属于经过解耦合的观察者模式。
桥接模式是一种 结构型设计模式,用于把抽象化与实现化解耦,使得二者可以独立变化。
组合模式 又叫部分整体模式,是一种 结构型设计模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!
参考资料:
- 百度百科 · 软件设计模式(设计模式)
- 菜鸟教程 · 设计模式
- JavaScript设计模式 【作者:千锋教育】

相关文章:
JavaScript设计模式(五)——发布订阅模式、桥接模式、组合模式
个人简介 👀个人主页: 前端杂货铺 🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…...
prize_p1
文章目录 解题过程代码审计思路问题解决数组绕过preg_match__destruct的触发修改phar文件以及签名phar://支持的后缀 题解方法一(数组绕过)方法二(gzip绕过) 解题过程 源代码 <META http-equiv"Content-Type" conte…...
Acwing 3534. 矩阵幂 3535. C翻转
3534. 矩阵幂 - AcWing题库 思路:模拟,当然,k次幂可以用快速幂优化,这里懒了 #include <iostream> #include <vector> using namespace std;vector<vector<int>> mul(int n, vector<vector<int>…...
Spring Cloud:构建微服务的最佳实践
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...
时间序列场景下多种数据填充算法实践与对比分析
在时间序列建模任务中,模型往往对于缺失数据是比较敏感的,大量的缺失数据甚至会导致训练出来的模型完全不可用,在我前面的博文中也有写到过数据填充相关的内容,感兴趣的话可以自行移步阅读即可: 《python 基于滑动平均…...
Mysql开启binlog
本案例基于mysql5.7.16实验 1、在linux中进入mysql查询binlog是否打开,执行命令如下: mysql -u root -p 2、查询binlog是否开启命令如下,如果log_bin为OFF则证明mysql的binlog没有打开 show variables like %log_bin%; 3、退出mysql终端&…...
【Java Web】HTML 标签 总结
目录 1.HTML 2.标签 1. head 标签 1.图标 2.样式居中 2. body 标签 1.注释 : 2.加载图片 3.加载视频 效果 4.区域 效果 5.上下跳转,页面跳转 效果 6.表格 效果 7.有序列表,无序列表 效果 8.登录 效果 9.按钮 10.多选框…...
前端面试的话术集锦第 4 篇:进阶篇下
这是记录前端面试的话术集锦第四篇博文——进阶篇下,我会不断更新该博文。❗❗❗ 1. 浏览器Eventloop和Node中的有什么区别 众所周知JS是⻔⾮阻塞单线程语⾔,因为在最初JS就是为了和浏览器交互⽽诞⽣的。 如果JS是⻔多线程的语⾔话,我们在多个线程中处理DOM就可能会发⽣问…...
mmap详解
想写一篇文章,详细的介绍一下mmap,主要是原理、用法、mmap泄露来进行介绍。说到mmap,首先得从堆空间说起。 申请堆空间 其实,不管是 32 位系统还是 64 位系统,内核都会维护一个变量 brk,指向堆的顶部&…...
项目02—基于keepalived+mysqlrouter+gtid半同步复制的MySQL集群
文章目录 一.项目介绍1.拓扑图2.详细介绍 二.前期准备1.项目环境2.IP划分 三. 项目步骤1.ansible部署软件环境1.1 安装ansible环境1.2 建立免密通道1.3 ansible批量部署软件1.4 统一5台mysql服务器的数据 2.配置基于GTID的半同步主从复制2.1 在master上安装配置半同步的插件,再…...
【EI征稿】第二届机械电子工程与人工智能国际学术会议(MEAI 2023)
第二届机械电子工程与人工智能国际学术会议(MEAI 2023) The 2nd International Conference on Mechatronic Engineering and Artificial Intelligence 2023年第二届机械电子工程与人工智能国际学术会议(MEAI 2023)计划将于2023年…...
ros2 学习launch文件组织工程 yaml配置文件
简单范例 功能描述 使用launch文件,统一管理工程,实现img转点云,发送到img_pt的topic,然后用reg_pcl节点进行subscribe,进行点云配准处理,输出融合后的点云到map_pt的topic。最后由rviz2进行点云展示。 …...
奇舞周刊第 505 期:实践指南-前端性能提升 270%!
记得点击文章末尾的“ 阅读原文 ”查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ 实践指南-前端性能提升 270% 当我们疲于开发一个接一个的需求时,很容易忘记去关注网站的性能,到了某一个节点,猛地发现,随着越来越多…...
【C++】泛型编程 | 函数模板 | 类模板
一、泛型编程 泛型编程是啥? 编写一种一般化的、可通用的算法出来,是代码复用的一种手段。 类似写一个模板出来,不同的情况,我们都可以往这个模板上去套。 举个例子: void Swap(int& a, int& b) {int tmp …...
web前端——简单的网页布局案列
✨博主:命运之光 🌸专栏:Python星辰秘典 🐳专栏:web开发(简单好用又好看) ❤️专栏:Java经典程序设计 ☀️博主的其他文章:点击进入博主的主页 目录 问题背景 解决样例 …...
线程安全问题(3)--- wait(),notify()
前言 在多线程的环境下,我们常常要协调多个线程之间的执行顺序,而为了实现这一点,Java提供了一些方法来帮助我们完成这一点。 一,wait() 作用: 使当前线程进入等待状态 释放当前的锁 (即该方法必须和 synchrnized 关键…...
【Android知识笔记】进程通信(一)
一、Android Framework 用到了哪些 IPC 方式 Linux 的 IPC 方式有: 管道Socket共享内存信号信号量消息队列管道通信 管道是基于pipefs文件系统实现的,也就是多个进程通过对同一个文件进行读写来实现进程间通信。半双工,单向的,通过 pipe(fds) 系统函数调用可得到一对文件描…...
存储空间压缩6倍 ,多点DMALL零售SaaS场景降本实践
🧑💼 作者简介 冯光普:多点 DMALL 数据库团队负责人,负责数据库稳定性建设与 DB PaaS 平台建设,在多活数据库架构、数据同步方案等方面拥有丰富经验。 杨家鑫:多点高级 DBA,擅长故障分析与性能…...
BGP路由属性
任何一条BGP路由都拥有多个路径属性(Path Attributes),当路由器通告BGP路由给它的对等体时,该路由将会携带多个路径属性,这些属性描述了BGP路由的各项特征,同时在某些场景下也会影响BGP路由优选的决策。 一…...
Java面试常用函数
1. charAt() 方法用于返回字符串指定索引处的字符。索引范围为从 0 到 length() - 1。 map.getOrDefault(num, 0) :如果map存在num这个key,则返回num对应的value,否则返回0. Arrays.sort(nums); 数组排序 Arrays.asList("a","b",&q…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
