当前位置: 首页 > news >正文

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();

在这里插入图片描述


🎉🎉本篇小结

本文我们了解了发布订阅模式、桥接模式、组合模式。

发布订阅模式 的发布者和订阅者不用相互知道,通过第三方实现调度,属于经过解耦合的观察者模式。

桥接模式是一种 结构型设计模式,用于把抽象化与实现化解耦,使得二者可以独立变化。

组合模式 又叫部分整体模式,是一种 结构型设计模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。

好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!


参考资料:

  1. 百度百科 · 软件设计模式(设计模式)
  2. 菜鸟教程 · 设计模式
  3. JavaScript设计模式 【作者:千锋教育】

在这里插入图片描述


相关文章:

JavaScript设计模式(五)——发布订阅模式、桥接模式、组合模式

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…...

prize_p1

文章目录 解题过程代码审计思路问题解决数组绕过preg_match__destruct的触发修改phar文件以及签名phar://支持的后缀 题解方法一&#xff08;数组绕过&#xff09;方法二&#xff08;gzip绕过&#xff09; 解题过程 源代码 <META http-equiv"Content-Type" conte…...

Acwing 3534. 矩阵幂 3535. C翻转

3534. 矩阵幂 - AcWing题库 思路&#xff1a;模拟&#xff0c;当然&#xff0c;k次幂可以用快速幂优化&#xff0c;这里懒了 #include <iostream> #include <vector> using namespace std;vector<vector<int>> mul(int n, vector<vector<int>…...

Spring Cloud:构建微服务的最佳实践

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

时间序列场景下多种数据填充算法实践与对比分析

在时间序列建模任务中&#xff0c;模型往往对于缺失数据是比较敏感的&#xff0c;大量的缺失数据甚至会导致训练出来的模型完全不可用&#xff0c;在我前面的博文中也有写到过数据填充相关的内容&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《python 基于滑动平均…...

Mysql开启binlog

本案例基于mysql5.7.16实验 1、在linux中进入mysql查询binlog是否打开&#xff0c;执行命令如下&#xff1a; mysql -u root -p 2、查询binlog是否开启命令如下&#xff0c;如果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.注释 &#xff1a; 2.加载图片 3.加载视频 效果 4.区域 效果 5.上下跳转&#xff0c;页面跳转 效果 6.表格 效果 7.有序列表&#xff0c;无序列表 效果 8.登录 效果 9.按钮 10.多选框…...

前端面试的话术集锦第 4 篇:进阶篇下

这是记录前端面试的话术集锦第四篇博文——进阶篇下,我会不断更新该博文。❗❗❗ 1. 浏览器Eventloop和Node中的有什么区别 众所周知JS是⻔⾮阻塞单线程语⾔,因为在最初JS就是为了和浏览器交互⽽诞⽣的。 如果JS是⻔多线程的语⾔话,我们在多个线程中处理DOM就可能会发⽣问…...

mmap详解

想写一篇文章&#xff0c;详细的介绍一下mmap&#xff0c;主要是原理、用法、mmap泄露来进行介绍。说到mmap&#xff0c;首先得从堆空间说起。 申请堆空间 其实&#xff0c;不管是 32 位系统还是 64 位系统&#xff0c;内核都会维护一个变量 brk&#xff0c;指向堆的顶部&…...

项目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)

第二届机械电子工程与人工智能国际学术会议&#xff08;MEAI 2023&#xff09; The 2nd International Conference on Mechatronic Engineering and Artificial Intelligence 2023年第二届机械电子工程与人工智能国际学术会议&#xff08;MEAI 2023&#xff09;计划将于2023年…...

ros2 学习launch文件组织工程 yaml配置文件

简单范例 功能描述 使用launch文件&#xff0c;统一管理工程&#xff0c;实现img转点云&#xff0c;发送到img_pt的topic&#xff0c;然后用reg_pcl节点进行subscribe&#xff0c;进行点云配准处理&#xff0c;输出融合后的点云到map_pt的topic。最后由rviz2进行点云展示。 …...

奇舞周刊第 505 期:实践指南-前端性能提升 270%!

记得点击文章末尾的“ 阅读原文 ”查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ 实践指南-前端性能提升 270% 当我们疲于开发一个接一个的需求时&#xff0c;很容易忘记去关注网站的性能&#xff0c;到了某一个节点&#xff0c;猛地发现&#xff0c;随着越来越多…...

【C++】泛型编程 | 函数模板 | 类模板

一、泛型编程 泛型编程是啥&#xff1f; 编写一种一般化的、可通用的算法出来&#xff0c;是代码复用的一种手段。 类似写一个模板出来&#xff0c;不同的情况&#xff0c;我们都可以往这个模板上去套。 举个例子&#xff1a; void Swap(int& a, int& b) {int tmp …...

web前端——简单的网页布局案列

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 目录 问题背景 解决样例 …...

线程安全问题(3)--- wait(),notify()

前言 在多线程的环境下&#xff0c;我们常常要协调多个线程之间的执行顺序&#xff0c;而为了实现这一点&#xff0c;Java提供了一些方法来帮助我们完成这一点。 一&#xff0c;wait() 作用&#xff1a; 使当前线程进入等待状态 释放当前的锁 (即该方法必须和 synchrnized 关键…...

【Android知识笔记】进程通信(一)

一、Android Framework 用到了哪些 IPC 方式 Linux 的 IPC 方式有: 管道Socket共享内存信号信号量消息队列管道通信 管道是基于pipefs文件系统实现的,也就是多个进程通过对同一个文件进行读写来实现进程间通信。半双工,单向的,通过 pipe(fds) 系统函数调用可得到一对文件描…...

存储空间压缩6倍 ,多点DMALL零售SaaS场景降本实践

&#x1f9d1;‍&#x1f4bc; 作者简介 冯光普&#xff1a;多点 DMALL 数据库团队负责人&#xff0c;负责数据库稳定性建设与 DB PaaS 平台建设&#xff0c;在多活数据库架构、数据同步方案等方面拥有丰富经验。 杨家鑫&#xff1a;多点高级 DBA&#xff0c;擅长故障分析与性能…...

BGP路由属性

任何一条BGP路由都拥有多个路径属性&#xff08;Path Attributes&#xff09;&#xff0c;当路由器通告BGP路由给它的对等体时&#xff0c;该路由将会携带多个路径属性&#xff0c;这些属性描述了BGP路由的各项特征&#xff0c;同时在某些场景下也会影响BGP路由优选的决策。 一…...

Java面试常用函数

1. charAt() 方法用于返回字符串指定索引处的字符。索引范围为从 0 到 length() - 1。 map.getOrDefault(num, 0) :如果map存在num这个key&#xff0c;则返回num对应的value&#xff0c;否则返回0. Arrays.sort(nums); 数组排序 Arrays.asList("a","b",&q…...

ModuleNotFoundError: No module named ‘ui_form‘

问题描述&#xff1a;在QT CREATER创建一个新的python QT项目后&#xff0c;若无法直接编译而是报错如下&#xff1a;解决办法&#xff1a; 在该项目的目录下输入cmd&#xff0c;打开命令行窗口——然后输入pyside6-uic form.ui -o ui_form.py 运行即可正常编译 &#xff08;若…...

卸载软件后右键菜单残留?用PowerShell精准清理注册表(附一键备份脚本)

彻底告别右键菜单残留&#xff1a;PowerShell注册表清理实战指南 刚卸载完某款压缩软件&#xff0c;却发现右键菜单里依然顽固地留着它的选项——这种经历恐怕不少Windows用户都遇到过。上周帮同事处理电脑时&#xff0c;就遇到了一个典型案例&#xff1a;卸载"可牛压缩&q…...

苹果为何拒绝TD-SCDMA特供版iPhone?复盘技术标准与市场时机的战略博弈

1. 项目概述&#xff1a;一场关于苹果与中国移动的世纪猜想2012年的科技圈&#xff0c;空气中弥漫着一股躁动与期待。几乎所有的行业分析师和手机发烧友都在讨论同一个话题&#xff1a;苹果公司是否会为了全球最大的移动运营商——中国移动&#xff0c;专门推出一款支持TD-SCDM…...

告别公网IP焦虑:用SakuraFrp免费隧道,5分钟搞定Linux服务器的SSH远程访问

5分钟实现无公网IP的Linux服务器远程访问&#xff1a;SakuraFrp实战指南 当你需要在外紧急处理家中或办公室的Linux服务器时&#xff0c;却发现没有公网IP无法远程连接&#xff0c;这种焦虑我深有体会。去年深夜的一次线上故障让我深刻认识到内网穿透工具的重要性——当时我正…...

基于Next.js 15与Sanity CMS构建高性能个人网站的技术实践

1. 项目概述&#xff1a;一个现代开发者的个人网站是如何炼成的 如果你是一名开发者&#xff0c;想搭建一个既能展示个人作品、又能写写技术博客&#xff0c;同时还得兼顾设计感和性能的个人网站&#xff0c;那么你大概率会和我一样&#xff0c;在技术选型上纠结很久。是直接用…...

[技术解析] 边缘结构模型MSM:破解时依性混杂的因果推断利器

1. 边缘结构模型MSM&#xff1a;因果推断的"时光机" 想象你是一名医生&#xff0c;正在研究某种降压药的长期疗效。患者A连续服药3个月后血压稳定&#xff0c;患者B服药1个月后自行停药导致血压反弹。传统统计方法会简单对比两组结果&#xff0c;但忽略了一个关键问…...

低成本传感器动态校准:SenDaL框架原理与应用

1. 低成本传感器校准的行业痛点与SenDaL解决方案在智能家居和工业物联网领域&#xff0c;我们经常面临一个尴尬的境地&#xff1a;高精度传感器价格昂贵难以大规模部署&#xff0c;而低成本传感器的数据质量又令人担忧。以PM2.5监测为例&#xff0c;专业级β射线传感器的价格可…...

Get-cookies.txt-LOCALLY:浏览器Cookie本地导出终极指南

Get-cookies.txt-LOCALLY&#xff1a;浏览器Cookie本地导出终极指南 【免费下载链接】Get-cookies.txt-LOCALLY Get cookies.txt, NEVER send information outside. 项目地址: https://gitcode.com/gh_mirrors/ge/Get-cookies.txt-LOCALLY 在数字时代&#xff0c;浏览器…...

算法23,寻找峰值

这是一道经典的二分查找应用题&#xff1a;寻找峰值&#xff08;Find Peak Element&#xff09;。笔记中已经总结了核心逻辑&#xff0c;我将为你梳理其背后的数学原理&#xff08;二段性&#xff09;&#xff0c;并提供标准的代码实现。1. 核心原理&#xff1a;什么是“二段性…...

Beyond Compare 5完全激活指南:3种简单方法告别30天试用限制

Beyond Compare 5完全激活指南&#xff1a;3种简单方法告别30天试用限制 【免费下载链接】BCompare_Keygen Keygen for BCompare 5 项目地址: https://gitcode.com/gh_mirrors/bc/BCompare_Keygen 你是否正在使用Beyond Compare 5这款强大的文件对比工具&#xff0c;却因…...