Javascript常见设计模式
JS设计模式学习【待吸收】-CSDN博客
JavaScript 中的设计模式是用来解决常见问题的最佳实践方案。这些模式有助于创建可重用、易于理解和维护的代码。下面列出了一些常见的 JavaScript 设计模式及其代码示例。
1. 单例模式(Singleton)
单例模式确保一个类仅有一个实例,并提供一个全局访问点。
class Singleton { static instance = null; constructor() { if (Singleton.instance) { return Singleton.instance; } Singleton.instance = this; // 初始化代码 this.data = {}; } getData() { return this.data; } setData(data) { this.data = data; }
} const instance1 = new Singleton();
const instance2 = new Singleton(); console.log(instance1 === instance2); // true
2. 工厂模式(Factory)
工厂模式用于创建对象,而无需指定具体类。
function createProduct(type) { switch(type) { case 'car': return new Car(); case 'bike': return new Bike(); default: return null; }
} class Car { constructor() { this.type = 'Car'; }
} class Bike { constructor() { this.type = 'Bike'; }
} const car = createProduct('car');
console.log(car.type); // Car
5. 代理模式(Proxy)
JavaScript ES6 引入了 Proxy 对象来定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等)。
let target = {};
let handler = { get: function(target, prop, receiver) { if (prop in target) { return target[prop]; } return `Unknown property '${prop}'`; }
}; let proxy = new Proxy(target, handler); console.log(proxy.foo); // "Unknown property 'foo'"
4.发布订阅模式与观察者模式
设计模式—观察者模式与发布订阅-CSDN博客
在 JavaScript 中,发布/订阅模式(Pub/Sub)和观察者模式(Observer Pattern)经常被视为相似或相关的设计模式,但它们之间确实存在一些细微的差别和不同的使用场景。尽管它们在很多方面都有重叠,但理解它们之间的差异对于正确选择和应用这些模式至关重要。
观察者模式(Observer Pattern)
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
- 主题(Subject):管理所有依赖于它的观察者对象,并在其内部状态发生改变时主动通知观察者。
- 观察者(Observer):为那些在主题对象发生改变时需要获得通知的对象提供一个统一的接口。
发布/订阅模式(Pub/Sub)
发布/订阅模式是一种消息传递模式,消息发送者(发布者)不会将消息直接发送给特定的接收者(订阅者)。相反,发布者将发布的消息分为不同的类别,并且无需了解哪些订阅者(如果有的话)会收到这个消息。同样,订阅者可以表达对一个或多个类别的兴趣,并且只接收感兴趣的消息,无需了解哪些发布者(如果有的话)会发布这个消息。
- 发布者(Publisher):不直接将消息发送给特定的订阅者,而是发布的消息到“频道”或“主题”。
- 消息代理(Message Broker):负责接收来自发布者的消息,并将这些消息分发给所有订阅了相应主题的订阅者。
- 订阅者(Subscriber):表达对一个或多个特定主题的兴趣,并接收来自这些主题的消息。
差异
-
解耦程度:虽然两者都提供了一定程度的解耦,但发布/订阅模式通常提供更高级别的解耦。在观察者模式中,观察者和主题之间通常存在直接的依赖关系,而在发布/订阅模式中,发布者和订阅者之间不需要知道对方的存在。
-
中介角色:在发布/订阅模式中,通常需要一个消息代理来作为中介,负责接收发布者的消息并将其分发给订阅者。而在观察者模式中,主题直接通知观察者,没有中介。
-
消息类型:在订阅发布/模式中,消息通常通过主题或频道进行分类,订阅者可以订阅一个或多个主题。在观察者模式中,观察者通常直接监听主题对象的特定状态变化。
示例代码(简化)
这里是一个简化的 JavaScript 示例,用于展示两种模式的实现:
观察者模式
class Subject { constructor() { this.observers = []; } subscribe(observer) { this.observers.push(observer); } unsubscribe(observer) { this.observers = this.observers.filter(obs => obs !== observer); } notify(data) { this.observers.forEach(observer => { observer.update(data); }); }
} class Observer { update(data) { console.log(`Observer received: ${data}`); }
} // 使用...
发布/订阅模式(简化,实际中可能需要更复杂的实现)
// 创建一个简单的发布订阅者管理类
class EventEmitter { constructor() { this.events = {}; // 用于存储事件的字典,键为事件名,值为订阅者数组 } // 订阅事件 on(eventName, callback) { if (!this.events[eventName]) { this.events[eventName] = []; // 如果该事件尚未被订阅,则初始化一个空数组 } this.events[eventName].push(callback); // 将回调函数添加到订阅者数组中 return this; // 支持链式调用 } // 取消订阅事件 off(eventName, callback) { if (this.events[eventName]) { // 移除指定的回调函数 this.events[eventName] = this.events[eventName].filter(cb => cb !== callback); // 如果订阅者数组为空,则删除该事件 if (this.events[eventName].length === 0) { delete this.events[eventName]; } } return this; // 支持链式调用 } // 发布事件 emit(eventName, ...args) { if (this.events[eventName]) { // 遍历订阅者数组,并执行每个回调函数 this.events[eventName].forEach(callback => { callback.apply(this, args); }); } return this; // 支持链式调用 } // 可选:监听一次后自动取消订阅 once(eventName, callback) { const onceCallback = (...args) => { callback.apply(this, args); this.off(eventName, onceCallback); }; this.on(eventName, onceCallback); return this; // 支持链式调用 }
} // 使用示例
const eventBus = new EventEmitter(); // 订阅者1
function subscriber1(price) { console.log('订阅者1收到消息:当前价格已降至' + price + '元');
} // 订阅者2
function subscriber2(price) { console.log('订阅者2也收到消息:价格更新为' + price + '元');
} // 订阅事件
eventBus.on('priceUpdate', subscriber1);
eventBus.on('priceUpdate', subscriber2); // 使用once方法监听一次
eventBus.once('specialOffer', (offer) => { console.log('只接收一次的特别优惠:' + offer);
}); // 发布事件
eventBus.emit('priceUpdate', 99); // 订阅者1和订阅者2都会收到消息
eventBus.emit('specialOffer', '买一赠一'); // 只有一个订阅者会收到这个特别优惠的消息 // 取消订阅
eventBus.off('priceUpdate', subscriber1);
eventBus.emit('priceUpdate', 88); // 只有订阅者2会收到消息
应用场景
- 观察者模式:
- 多用于单个应用内部,特别是在需要实现对象间的一对多依赖关系时。
- 例如,在图形用户界面(GUI)框架中,按钮的点击事件、窗口的打开和关闭事件等都可以使用观察者模式进行处理。
- 另一个例子是股票市场,股票交易所可以充当被观察者,而股票交易员可以充当观察者,当股票价格、交易量等发生变化时,交易员将接收到通知。
- 发布/订阅模式:
- 更多的是一种跨应用的模式(cross-application pattern),适用于需要在不同系统或组件之间进行通信的场景。
- 例如,在微服务架构中,服务之间的通信经常采用发布/订阅模式,通过消息队列或事件总线进行异步通信。
- 在前端开发中,发布/订阅模式也常用于实现组件间的通信,特别是在Vue、React等现代前端框架中,通过事件总线或全局状态管理库(如Redux、Vuex)来实现跨组件的通信。
- 自定义事件:在前端开发中,可以创建自定义事件,让组件或模块之间通过事件进行通信。
- 状态管理:在前端状态管理库(如Redux、Vuex)中,发布订阅模式是实现状态更新的核心机制。
- 异步编程:在异步编程中,发布订阅模式可以帮助我们解耦异步操作和它们的回调函数。
- 插件系统:在插件系统中,发布订阅模式可以让插件之间以解耦的方式进行通信。
3. 策略模式(Strategy)
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
一、定义与原理
策略模式定义了一系列的算法,并将每个算法封装起来,使它们可以相互替换。在JavaScript中,策略模式通常通过函数或对象来实现,每个策略都是一个独立的函数或对象,封装了具体的算法逻辑。客户端可以根据需要选择不同的策略来执行相应的算法。
二、结构组成
一个基于策略模式的程序通常包含以下两部分:
- 策略类(Strategy):封装了具体的算法或行为,每个策略类都实现了相同的接口(在JavaScript中通常是通过函数参数或方法签名来保证的)。
- 环境类(Context):也被称为上下文类,它接受客户的请求,并根据需要选择合适的策略类来执行算法。环境类维护了一个对策略对象的引用,并在需要时调用其算法。
三、应用场景
策略模式在JavaScript中有着广泛的应用场景,包括但不限于:
- 表单验证:根据不同的验证规则创建不同的策略对象,并将其注入到表单验证器中,实现灵活的表单验证。
- 排序算法:将排序算法封装在不同的策略对象中,根据需要选择不同的排序算法。
- 动画效果:将不同的动画算法封装在独立的策略对象中,根据用户的操作来动态地选择不同的动画效果。
- 缓动函数:封装不同的缓动算法,使缓动函数可以根据不同的缓动算法来执行不同的效果。
class Strategy { doOperation(num1, num2) { throw new Error('This method must be overridden!'); }
} class AddStrategy extends Strategy { doOperation(num1, num2) { return num1 + num2; }
} class SubtractStrategy extends Strategy { doOperation(num1, num2) { return num1 - num2; }
} class Context { constructor(strategy) { this.strategy = strategy; } executeStrategy(num1, num2) { return this.strategy.doOperation(num1, num2); }
} const context = new Context(new AddStrategy());
console.log(context.executeStrategy(5, 3)); // 8 context.strategy = new SubtractStrategy();
console.log(context.executeStrategy(5, 3)); // 2
相关文章:
Javascript常见设计模式
JS设计模式学习【待吸收】-CSDN博客 JavaScript 中的设计模式是用来解决常见问题的最佳实践方案。这些模式有助于创建可重用、易于理解和维护的代码。下面列出了一些常见的 JavaScript 设计模式及其代码示例。 1. 单例模式(Singleton) 单例模式确保一…...
JavaFX布局-SplitPane
JavaFX布局-SplitPane 常用属性orientationpaddingdividerPositionsdisable 实现方式Java实现fxml实现 一个拆分至少两个区域的容器支持水平、垂直布局可以拖动区域的大小初始化大小通过比例设置[0,1] 常用属性 orientation 排列方式,Orientation.VERTICAL、Orien…...
2.MySQL库的操作
创建数据库 创建数据库的代码: CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [,create_specification] ...];create_specification:[DEFAULT] CHARACTER SET charset_name[DEFAULT] COLLATE collation_name 说明: 大写的表示关键…...
如何学习计算机
不要只盯着计算机语言学习,你现在已经学习了C语言和Java,暑假又规划学习Python,最后你掌握的就是计算机语言包而已。 2. 建议你找一门想要深挖的语言,沿着这个方向继续往后学习知识就行。计算机语言是学不完的,而未来就…...
Spring MVC 快速入门指南及实战演示
1、SpringMVC简介 1.1 背景 Servlet属于web层开发技术,技术特点: 1. 每个请求都需要创建一个Servlet进行处理 2. 创建Servlet存在重复操作 3. 代码灵活性低,开发效率低 是否有技术方案可以解决以上问题? 1.2 SpringMVC概述 Sp…...
在线测评系统(未完结)
文章目录 注意!!!1、多模块开发(后端)(1).Maven依赖(2)swagger配置 2、判题机开发(1)docker 前言:大二刚开始接手了本学院的oj,并管理了一段时间,后来老师给我…...
Python 爬虫项目实战(一):破解网易云 VIP 免费下载付费歌曲
前言 网络爬虫(Web Crawler),也称为网页蜘蛛(Web Spider)或网页机器人(Web Bot),是一种按照既定规则自动浏览网络并提取信息的程序。爬虫的主要用途包括数据采集、网络索引、内容抓…...
PTA 6-7 统计某类完全平方数
6-7 统计某类完全平方数(20分) 本题要求实现一个函数,判断任一给定整数N是否满足条件:它是完全平方数,又至少有两位数字相同,如144、676等。 函数接口定义: int IsTheNumber ( const int N );…...
PyFilesystem2 - Python 操作文件系统
文章目录 一、关于 PyFilesystem2二、安装三、快速使用四、指南为什么要使用 PyFilesystem ?打开文件系统树打印关闭目录信息子目录处理文件遍历 WalkingGlobbing移动和复制 五、概念路径系统路径沙盒错误 六、资源信息信息对象命名空间基本命名空间细节命名空间访问…...
Bug小记:关于servlet后端渲染界面时出现的问题小记1P
问题1: 问题描述: int delete(Integer Sno);后端在该方法调用时传入参数 req.getParameter("Sno")报错参数应该为Integer类型问题分析:后端通过请求获取到的前端数据都是字符串类型,需要手动转换参数类型 解决方法&a…...
智慧水务项目(二)django(drf)+angular 18 创建通用model,并对orm常用字段进行说明
一、说明 上一篇文章建立一个最简单的项目,现在我们建立一个公共模型,抽取公共字段,以便于后续模块继承,过程之中会对orm常用字段进行说明,用到的介绍一下 二、创建一个db.py 目录如下图 1、代码 from importlib im…...
<数据集>人员摔倒识别数据集<目标检测>
数据集格式:VOCYOLO格式 图片数量:8605张 标注数量(xml文件个数):8605 标注数量(txt文件个数):8605 标注类别数:1 标注类别名称:[fall] 序号类别名称图片数框数1fall860512275 使用标注工具…...
npm install 报错 ‘proxy‘ config is set properly. See: ‘npm help config‘
解决 参考链接:npm install 报错 ‘proxy‘ config is set properly. See: ‘npm help config‘-阿里云开发者社区 (aliyun.com)...
爬虫问题---ChromeDriver的安装和使用
一、安装 1.查看chrome的版本 在浏览器里面输入 chrome://version/ 回车查看浏览器版本 Chrome的版本要和ChromeDriver的版本对应,否则会出现版本问题。 2.ChromeDriver的版本选择 114之前的版本:https://chromedriver.storage.googleapis.com/index.ht…...
Spring的配置类分为Full和Lite两种模式
Spring的配置类分为Full和Lite两种模式 首先查看 Configuration 注解的源码, 如下所示: Target({ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Documented Component public interface Configuration {AliasFor(annotation Component.class)String value() defau…...
探索Perl的代码生成艺术:利用编译器后端释放潜能
探索Perl的代码生成艺术:利用编译器后端释放潜能 Perl,作为一种解释型语言,通常不通过编译器后端直接生成机器代码。然而,通过一些高级技术,Perl 程序员可以利用编译器后端来生成代码,从而提高性能或实现特…...
21 B端产品经理之技术常识(1)
产品经理需要掌握一些基本的技术知识。 了解公司前端与后端 前端 前端开发:创建WEB页面或APP等前端界面呈现给用户的过程,即前端负责用户界面交互。 前端技能: HTML:一种标记语言,能够实现Web页面并在浏览器中显示。…...
数据结构基础详解(C语言):单链表_定义_初始化_插入_删除_查找_建立操作_纯c语言代码注释讲解
单链表理论知识详解 文章目录 单链表理论知识详解1.单链表的定义2.单链表的初始化3.单链表的插入和删除3.1 单链表的插入3.1.1 按位序插入3.1.2 在指定结点的前后插入一.后插操作二.前插操作 4.单链表的删除4.1 按位序删除4.2 指定结点的删除 5.单链表的查找5.1 按位序查找5.2 …...
【智能时代的创新工具】LangChain快速入门指南:轻松掌握语言模型的集成与运用
一、LangChain:连接语言模型与现实世界的桥梁 1.1 LangChain的定义与重要性 LangChain是一个开源的Python库,它旨在为开发人员提供一种简便的方式来集成和运用语言模型。它不仅仅是一个简单的API调用工具,而是一个具有丰富功能的框架&#x…...
文献阅读:细胞分辨率全脑图谱的交互式框架
文献介绍 文献题目: An interactive framework for whole-brain maps at cellular resolution 研究团队: Daniel Frth(瑞典卡罗林斯卡学院)、Konstantinos Meletis(瑞典卡罗林斯卡学院) 发表时间ÿ…...
YAML基础语言深度解析
引言 YAML(YAML Aint Markup Language,即YAML不是一种标记语言)是一种直观、易于阅读的数据序列化格式,常用于配置文件、数据交换和程序间的通信。其设计目标是易于人类阅读和编写,同时也便于机器解析和生成。在本文中…...
xcode使用
1. 界面 1.1. Build Settings,Build Phases和Build Rules三个设置项 Build Settings(编译设置): 每个选项由标题(Title)和定义(Definition)组成。这里主要定义了Xcode在编译项目时的一些具体配置 Build Phases(编译资源):用于指定编译过程中项目所链接的原文件,依赖对象,库…...
OV2640引脚的定义(OV2640 FPC模组规格书(接口线序))
OV2640是一款由Omni Vision公司生产的1/4寸CMOS UXGA(1632x1222)图像传感器。这款传感器以其小巧的体积、低工作电压和强大的功能而著称,它集成了单片UXGA摄像头和影像处理器,能够通过SCCB总线控制输出各种分辨率的8/10位影像数据…...
CTFSHOW 萌新 web10 解题思路和方法(passthru执行命令)
点击题目链接,分析页面代码。发现代码中过滤了system、exec 函数,这意味着我们不能通过system(cmd命令)、exec(cmd命令)的方式运行命令。 在命令执行中,常用的命令执行函数有: system(cmd_code);exec(cmd_…...
深入Java数据库连接和JDBC
引言 Java数据库连接(JDBC)是Java语言中用于执行SQL语句的标准API。通过JDBC,开发者可以方便地与关系型数据库进行交互。然而,直接使用JDBC API面临着数据库连接管理复杂、性能瓶颈等问题。数据库连接池作为一种解决方案,可以有效地管理数据库连接,提高应用程序的性能。…...
灰狼优化算法(GWO)与长短期记忆网络(LSTM)结合的预测模型(GWO-LSTM)及其Python和MATLAB实现
#### 一、背景 在现代数据科学和人工智能领域,预测模型的准确性和效率是研究者和工程师不断追求的目标,尤其是在时间序列预测、金融市场分析、气象预测等领域。长短期记忆(LSTM)网络是一种解决传统递归神经网络(RNN&a…...
电路板热仿真覆铜率,功率,结温,热阻率信息计算获取方法总结
🏡《电子元器件学习目录》 目录 1,概述2,覆铜率3,功率4,器件尺寸5,结温6,热阻1,概述 电路板热仿真操作是一个复杂且细致的过程,旨在评估和优化电路板内部的热分布及温度变化,以确保电子元件的可靠性和性能。本文简述在进行电路板的热仿真时,元器件热信息的计算方法…...
C#中多线程编程中的同步、异步、串行、并行及并发及死锁
在C#中,多线程编程是一个强大的功能,它允许程序同时执行多个任务。然而,这也带来了复杂性,特别是在处理同步、异步、串行、并行、并发以及死锁等问题时。下面我将详细解释这些概念,并给出一些C#中的示例和注意事项。 …...
【Lampiao靶场渗透】
文章目录 一、IP地址获取 二、信息收集 三、破解SSH密码 四、漏洞利用 五、提权 一、IP地址获取 netdiscover -i eth0 Arp-scan -l Nmap -sP 192.168.78.0/24 靶机地址:192.168.78.177 Kali地址:192.168.78.128 二、信息收集 nmap -sV -p- 192.…...
使用WebSocket实现log日志流的实时展示-从轮询到通知
场景介绍 最近开发一个系统,其中一个模块需要展示实时的执行过程,过程日志可能比较多。以前的方案都是前端定时轮询,比如每秒查一次后端接口,将拉取回来的日志重新展示。轮询方案简单容易实现,但是比较消耗资源&#…...
做电商网站一般多少钱/seo百度首页排名业务
接收从控制台输入的数据可以使用Scanner类实现,Scanner类在一个名为util的包中需要在程序中导入这个包, 即在程序中添加import java.util.*;Scanner类可以接收int string char boolean 等类型数据,其中string类型数据使用next() 或者 nextLin…...
做网站需要那些编程语言/网络营销策略主要包括
文章目录hashmap基础hashmap的nodehashmap的容量hashmap的负载因子hashmap的hash()算法HashMap里面的hash()返回值hashmap的数组链表/树问题hashmap为什么引入链表为什么jdk1.8会引入红黑树呢hashmap为什么一开始不就使用红黑树?HashMap的底层数组取值的时候&#x…...
wordpress背景图美化/百度热搜榜单
windows是个多用户多任务的操作系统,支持多个程序同时运行,如果你的程序不想让用户同时运行一个以上, 那应该怎样做呢? 本文将介绍避免用户同时运行多个程序的例子。 需要用到的函数CreateMutex ,CreateMutex 函数是…...
动态网站开发概述/软文投放平台有哪些?
partition[英][pɑ:ˈtiʃən] [美][pɑrˈtɪʃən] 简明释义n.划分,分开;分割;隔离物;隔墙 vt.分开,隔开;区分;分割 转载于:https://www.cnblogs.com/wwjyt/archive/2013/02/23/3153124.html...
手机nfc网站开发/东莞优化seo
欢迎进入Linux社区论坛,与200万技术人员互动交流 >>进入 1、出现的问题? JEECMS套件(jeecms-2012-sp1)中有一个jeecms-db-2012-sp1.sql文件,文件里面有一张"jc_file"的表,表里面有一个字段"file_path"的…...
手机网站建设服务电话/精准粉丝引流推广
在开发大型应用程序的时候,都是(非常有必要)将程序按照单元功能(模块)分开,即程序的模块化。然而有时因为模块功能函数划分太多,难以避免导致当前的头文件被重复#include的情况,这时便会出现重复定义的错误。于是为了解决这种情况…...