JavaScript 行为型设计模式详解

1. 观察者模式

1.1. 使用场景

观察者模式用于对象间的一对多依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都能收到通知并自动更新。常用于事件处理、通知系统。在前端中,观察者模式用于实现事件监听、数据绑定等功能。

1.2. 代码实现

class Subject {constructor() {this.observers = [];}addObserver(observer) {this.observers.push(observer);}removeObserver(observer) {this.observers = this.observers.filter(obs => obs !== observer);}notifyObservers(message) {this.observers.forEach(observer => observer.update(message));}
}class Observer {update(message) {console.log('Observer received:', message);}
}// 使用观察者模式
const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();subject.addObserver(observer1);
subject.addObserver(observer2);subject.notifyObservers('New update available'); // Observer received: New update available

1.3. 详细解释

  • Subject:发布者,维护一个观察者列表,提供方法来添加、移除和通知观察者。

  • Observer:观察者,提供 update 方法来响应发布者的通知。

  • 观察者模式适合事件系统或数据模型更新的场景。

1.4. 实际应用

观察者模式常用于事件驱动系统,如 DOM 事件监听器、Vue 或 React 的响应式系统。

2. 发布订阅模式

2.1. 使用场景

发布订阅模式用于实现松耦合的事件驱动系统,发布者(Publisher)和订阅者(Subscriber)通过事件中心(Event Bus或Broker)进行通信,发布者无需知道谁订阅了事件,而订阅者也无需知道事件由谁发布。该模式常用于消息队列、事件系统、异步处理等场景。

2.2. 代码实现

// 事件中心(Event Bus)
class EventBus {constructor() {this.subscribers = {}; // 存储所有事件和其对应的订阅者}// 订阅事件subscribe(event, callback) {if (!this.subscribers[event]) {this.subscribers[event] = []; // 如果事件不存在,创建一个新的订阅者列表}this.subscribers[event].push(callback); // 将订阅者的回调函数加入列表}// 发布事件publish(event, data) {if (this.subscribers[event]) {this.subscribers[event].forEach(callback => callback(data)); // 通知所有订阅者}}// 取消订阅unsubscribe(event, callback) {if (this.subscribers[event]) {this.subscribers[event] = this.subscribers[event].filter(cb => cb !== callback); // 移除指定的订阅者}}
}// 创建事件中心
const eventBus = new EventBus();// 订阅者1
const subscriber1 = (data) => {console.log('Subscriber 1 received:', data);
};// 订阅者2
const subscriber2 = (data) => {console.log('Subscriber 2 received:', data);
};// 订阅事件
eventBus.subscribe('eventA', subscriber1);
eventBus.subscribe('eventA', subscriber2);// 发布事件
eventBus.publish('eventA', 'This is event A data');
// Subscriber 1 received: This is event A data
// Subscriber 2 received: This is event A data// 取消订阅者2的订阅
eventBus.unsubscribe('eventA', subscriber2);// 再次发布事件
eventBus.publish('eventA', 'This is new event A data');
// Subscriber 1 received: This is new event A data

2.3. 详细注释

  • EventBus(事件中心):作为中介,维护一个事件和订阅者的映射关系。负责发布事件、添加订阅者以及移除订阅者。

  • subscribe:用于订阅某个事件,将订阅者的回调函数加入到对应事件的订阅者列表中。

  • publish:用于发布某个事件,触发该事件的所有订阅者的回调函数。

  • unsubscribe:取消订阅某个事件,移除指定订阅者的回调函数。

2.4. 实际应用

  • 在前端开发中,发布订阅模式常用于事件中心管理事件流,比如在 Vue.js 的 emit和on 中。

  • 消息队列系统(如 RabbitMQ、Kafka)也是发布订阅模式的典型应用。

3. 模板方法模式

3.1. 使用场景

模板方法模式定义了一个操作中的算法骨架,而将一些步骤的实现延迟到子类。常用于固定流程中部分步骤需要定制的场景。在前端中,模板方法模式可用于不同页面之间的结构共享。

3.2. 代码实现

class AbstractClass {templateMethod() {this.step1();this.step2();this.step3();}step1() {console.log('AbstractClass: Step 1');}step2() {throw new Error('step2 must be implemented by subclass');}step3() {console.log('AbstractClass: Step 3');}
}class ConcreteClass extends AbstractClass {step2() {console.log('ConcreteClass: Step 2');}
}// 使用模板方法模式
const instance = new ConcreteClass();
instance.templateMethod();
// Output:
// AbstractClass: Step 1
// ConcreteClass: Step 2
// AbstractClass: Step 3

3.3. 详细注释

  • AbstractClass:提供算法的骨架,定义了 templateMethod 作为算法的模板方法,具体步骤由子类实现。

  • ConcreteClass:子类实现了模板方法中的具体步骤。

  • 模板方法模式允许子类在不改变算法整体结构的前提下,重新定义算法的某些步骤。

3.4. 实际应用

  • 模板方法模式常用于页面加载逻辑、复杂流程处理等场景,如表单验证步骤、数据处理流程等。

4. 策略模式

4.1. 使用场景

策略模式定义了一系列算法,并将每个算法封装起来,使它们可以互换使用。在前端开发中,策略模式可以用于处理不同的用户输入、动态选择不同的 UI 渲染逻辑等。

4.2. 代码实现

class StrategyA {execute() {console.log('Executing Strategy A');}
}class StrategyB {execute() {console.log('Executing Strategy B');}
}class Context {setStrategy(strategy) {this.strategy = strategy;}executeStrategy() {this.strategy.execute();}
}// 使用策略模式
const context = new Context();
const strategyA = new StrategyA();
context.setStrategy(strategyA);
context.executeStrategy(); // Executing Strategy Aconst strategyB = new StrategyB();
context.setStrategy(strategyB);
context.executeStrategy(); // Executing Strategy B

4.3. 详细注释

  • StrategyA 和 StrategyB:定义了不同的算法实现。

  • Context:上下文类,维护当前策略,并通过 setStrategy 方法动态切换策略。

  • 策略模式允许在运行时根据条件选择不同的算法,避免使用大量条件语句。

4.4. 实际应用

  • 策略模式常用于表单验证、输入处理、动态 UI 渲染等场景。

5. 责任链模式

5.1. 使用场景

责任链模式用于将请求的处理者串联起来,多个对象依次处理请求,直到有对象处理它为止。在前端中,责任链模式常用于事件处理链、表单验证流程等。

5.2. 代码实现

class Handler {setNext(handler) {this.nextHandler = handler;}handle(request) {if (this.nextHandler) {return this.nextHandler.handle(request);}return null;}
}class ConcreteHandlerA extends Handler {handle(request) {if (request === 'A') {return 'Handled by A';}return super.handle(request);}
}class ConcreteHandlerB extends Handler {handle(request) {if (request === 'B') {return 'Handled by B';}return super.handle(request);}
}// 使用责任链模式
const handlerA = new ConcreteHandlerA();
const handlerB = new ConcreteHandlerB();
handlerA.setNext(handlerB);console.log(handlerA.handle('A')); // Handled by A
console.log(handlerA.handle('B')); // Handled by B

5.3. 详细注释

  • Handler:处理者的基类,提供 setNext 方法来设置下一个处理者。

  • ConcreteHandlerA 和 ConcreteHandlerB:具体处理者,实现了请求处理逻辑。

  • 责任链模式使得多个处理者依次处理请求,避免了请求和处理者之间的紧耦合。

5.4. 实际应用

  • 责任链模式常用于表单验证、事件处理链、权限管理等场景。

6. 中介者模式

6.1. 使用场景

中介者模式用于定义对象间的通信方式,避免直接交互造成的复杂性。在前端中,中介者模式常用于组件之间的通信、事件总线等。

6.2. 代码实现

class Mediator {notify(sender, event) {if (event === 'EventA') {console.log('Mediator reacts to EventA and triggers EventB');sender.trigger('EventB');}}
}class Component {constructor(mediator) {this.mediator = mediator;}trigger(event) {console.log(`Component triggered: ${event}`);this.mediator.notify(this, event);}
}// 使用中介者模式
const mediator = new Mediator();
const component = new Component(mediator);component.trigger('EventA');/* Output:
Component triggered: EventA
Mediator reacts to EventA and triggers EventB
Component triggered: EventB
*/

6.3. 详细注释

  • Mediator:中介者类,负责协调不同组件之间的交互。

  • Component:组件类,负责触发事件并通过中介者进行通信。

  • 中介者模式通过集中化的中介者,避免了多个组件之间的复杂依赖关系。

6.4. 实际应用

  • 中介者模式常用于组件通信、消息总线、事件系统等场景。

7. 访问者模式

7.1. 使用场景

访问者模式用于在不改变数据结构的前提下,定义对数据结构中元素的操作。在前端中,访问者模式适用于复杂结构的遍历和操作,如 DOM 树操作等。

7.2. 代码实现

class Element {accept(visitor) {visitor.visit(this);}
}class ConcreteElementA extends Element {operationA() {console.log('Operation A');}
}class ConcreteElementB extends Element {operationB() {console.log('Operation B');}
}class Visitor {visit(element) {if (element instanceof ConcreteElementA) {element.operationA();} else if (element instanceof ConcreteElementB) {element.operationB();}}
}// 使用访问者模式
const elements = [new ConcreteElementA(), new ConcreteElementB()];
const visitor = new Visitor();
elements.forEach(element => element.accept(visitor));

7.3. 详细注释

  • Element:元素基类,定义 accept 方法来接受访问者。

  • Visitor:访问者类,提供 visit 方法处理不同的元素类型。

  • 访问者模式允许在不修改数据结构的前提下,动态为结构中的每个元素定义新的操作。

7.4. 实际应用

  • 访问者模式常用于对树形结构、DOM 元素的遍历操作。

8. 命令模式

8.1. 使用场景

命令模式用于将请求封装为对象,从而实现请求的参数化、队列化。在前端中,命令模式适用于实现操作历史、撤销功能等场景。

8.2. 代码实现

class Command {execute() {throw new Error('execute method must be implemented');}
}class ConcreteCommand extends Command {constructor(receiver) {super();this.receiver = receiver;}execute() {this.receiver.action();}
}class Receiver {action() {console.log('Receiver action executed');}
}class Invoker {setCommand(command) {this.command = command;}executeCommand() {this.command.execute();}
}// 使用命令模式
const receiver = new Receiver();
const command = new ConcreteCommand(receiver);
const invoker = new Invoker();invoker.setCommand(command);
invoker.executeCommand(); // Receiver action executed

8.3. 详细注释

  • Command:命令的基类,定义 execute 方法。

  • ConcreteCommand:具体命令,执行对接收者的操作。

  • Invoker:调用者,负责执行命令。

  • 命令模式通过封装请求,将请求处理逻辑与请求发出者解耦。

8.4. 实际应用

  • 命令模式常用于实现操作历史、撤销重做、宏命令等场景。

9. 解释器模式

9.1. 使用场景

解释器模式用于给定语言的语法表达式,并解析其中的语句。在前端中,解释器模式可用于解析自定义的模板语言、脚本等。

9.2. 代码实现

class Expression {interpret(context) {throw new Error('interpret method must be implemented');}
}class NumberExpression extends Expression {constructor(value) {super();this.value = value;}interpret() {return this.value;}
}class AddExpression extends Expression {constructor(left, right) {super();this.left = left;this.right = right;}interpret() {return this.left.interpret() + this.right.interpret();}
}// 使用解释器模式
const left = new NumberExpression(3);
const right = new NumberExpression(5);
const addExpr = new AddExpression(left, right);console.log(addExpr.interpret()); // 8

9.3. 详细注释

  • Expression:解释器基类,定义 interpret 方法。

  • NumberExpression 和 AddExpression:具体的解释器,解析数字和加法操作。

  • 解释器模式允许定义一个简单的语言或规则,并通过解释器解析和执行。

9.4. 实际应用

  • 解释器模式常用于处理模板引擎、正则表达式解析等场景。

10. 迭代器模式

10.1. 使用场景

迭代器模式用于顺序访问集合对象的元素,而无需暴露其内部结构。在前端中,迭代器模式常用于遍历数组、集合等数据结构。

10.2. 代码实现

class Iterator {constructor(collection) {this.collection = collection;this.index = 0;}hasNext() {return this.index < this.collection.length;}next() {return this.collection[this.index++];}
}// 使用迭代器模式
const collection = [1, 2, 3, 4];
const iterator = new Iterator(collection);while (iterator.hasNext()) {console.log(iterator.next()); // 1 2 3 4
}

10.3. 详细注释

  • Iterator:迭代器类,提供 hasNext 和 next 方法来顺序访问集合中的元素。

  • 迭代器模式允许分离集合对象的遍历逻辑,使得遍历和数据结构解耦。

10.4. 实际应用

  • 迭代器模式常用于处理数组、链表、树等数据结构的遍历。

11. 备忘录模式

11.1. 使用场景

备忘录模式用于保存对象的状态,以便在需要时恢复。在前端中,备忘录模式可用于实现撤销功能、保存表单状态等。

11.2. 代码实现

class Memento {constructor(state) {this.state = state;}getState() {return this.state;}
}class Originator {setState(state) {console.log('Setting state to:', state);this.state = state;}saveStateToMemento() {return new Memento(this.state);}getStateFromMemento(memento) {this.state = memento.getState();}
}class Caretaker {constructor() {this.mementoList = [];}
}// 使用备忘录模式
const originator = new Originator();
const caretaker = new Caretaker();originator.setState('State 1');
caretaker.add(originator.saveStateToMemento());originator.setState('State 2');
caretaker.add(originator.saveStateToMemento());originator.setState('State 3');
console.log('Current State:', originator.state); // Current State: State 3originator.getStateFromMemento(caretaker.get(0));
console.log('Restored State:', originator.state); // Restored State: State 1

11.3. 详细注释

  • Memento:备忘录类,保存状态。

  • Originator:原始对象,提供保存和恢复状态的方法。

  • Caretaker:管理备忘录列表。

  • 备忘录模式通过保存对象的状态,允许在需要时恢复之前的状态。

11.4. 实际应用

  • 备忘录模式常用于实现撤销功能、表单状态恢复等场景。

12. 状态模式

12.1. 使用场景

状态模式允许对象在内部状态发生改变时,改变其行为。在前端中,状态模式可用于管理复杂的组件状态,如表单验证、UI 状态管理等。

12.2. 代码实现

class State {handle(context) {throw new Error('handle method must be implemented');}
}class ConcreteStateA extends State {handle(context) {console.log('State A, transitioning to State B');context.setState(new ConcreteStateB());}
}class ConcreteStateB extends State {handle(context) {console.log('State B, transitioning to State A');context.setState(new ConcreteStateA());}
}class Context {constructor() {this.state = new ConcreteStateA();}setState(state) {this.state = state;}request() {this.state.handle(this);}
}// 使用状态模式
const context = new Context();
context.request(); // State A, transitioning to State B
context.request(); // State B, transitioning to State A

12.3. 详细注释

  • State:状态基类,定义 handle 方法。

  • ConcreteStateA 和 ConcreteStateB:具体状态类,实现了状态切换逻辑。

  • Context:上下文类,负责在不同状态下切换并调用状态行为。

  • 状态模式允许对象在状态变化时改变其行为,使得状态切换透明化。

12.4. 实际应用

  • 状态模式常用于处理复杂的状态逻辑,如表单的验证状态、UI 的显示状态等。

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

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

相关文章

指令查找表LUT

本文整理自22. FlexSPI—读写外部SPI NorFlash — [野火]i.MX RT库开发实战指南——基于i.MXRT1052 文档 用作个人学习和分享 指令查找表LUT 访问FLASH存储器通常包含一些读写功能的的控制指令&#xff0c;主控设备可通过这些指令访问FLASH存储器。 为了适应这种需求&#…

uv使用指南

&#x1f680; Python 打包工具 UV 使用指南 UV 是一个用 Rust 编写的极速 Python 包管理器和解析器&#xff0c;旨在成为 pip、pip-tools、virtualenv 等工具的单一替代方案。 &#x1f4cb; 目录 核心概念与设计哲学安装与配置基础使用方法项目管理与工作流高级功能与技巧…

安卓学习 之 图片控件和图片按钮

今天学习的是ImageView 和 ImageButton这两个控件还是比较简单的&#xff1a;先来看看最后的样式图片吧&#xff1a;从图片中可以看到ImageView中的图片要大很多&#xff0c;这是因为中的ImageView中的图片跟ImageView控件的大小而自动调整。Imag…

动态规划-学习笔记

这是一份动态规划&#xff08;Dynamic Programming, DP&#xff09;完整学习笔记。笔记将从一星难度&#xff08;入门&#xff09;到五星难度&#xff08;进阶&#xff09;&#xff0c;循序渐进&#xff0c;涵盖核心思想、经典模型和解题方法论。 本来打算今天更新背包问题的题…

Linux 可信启动深度解析:从UEFI到操作系统的信任链

文章目录引言一、 可信根基&#xff1a;TPM与核心概念1.1 什么是“度量” (Measurement)&#xff1f;1.2 信任链与TPM PCR二、 阶段一&#xff1a;固件的可信启动 (UEFI)2.1 引导的起点&#xff1a;从SEC到DXE的初始化2.2 引导设备选择 (BDS)&#xff1a;UEFI如何找到GRUB2.3 S…

61-python中面向对象三大特性

前言&#xff1a; 面向对象编程&#xff0c;是许多编程语言都支持的一种编程思想。简单理解是&#xff1a;基于模板&#xff08;类&#xff09;去创建实体&#xff08;对象&#xff09;&#xff0c; 使用对象完成功能开发。面向对象包含三大主要特性&#xff1a; 封装 继承 多态…

BP-Adaboost模型

BP-Adaboost模型是一种将BP神经网络作为弱分类器的集成学习框架&#xff0c;通过AdaBoost算法动态调整样本权重和模型权重&#xff0c;显著提升预测精度和泛化能力。一、模型架构与工作原理 1. 基础框架 弱分类器单元&#xff1a;采用单隐藏层BP神经网络&#xff08;结构示例&a…

k230 +canMV+ LVGL控件 仿手表表盘触摸屏滚动、选中后弹窗效果完整示例程序

现在智能手表用的越来越多,其交互方式比较有特点,现在k230开发板上,基于LVGL(Light and Versatile Graphics Library)编写一个嵌入式GUI应用程序,使用LVGL配合触摸屏实现模仿智能手表的表盘滚动效果,实际效果如下: 程序使用LVGL图形库和MediaManager程序,创建带有触摸…

使用Vue.js和WebSocket打造实时库存仪表盘

大家好&#xff01;今天我将分享一个简单却强大的实时库存仪表盘项目&#xff0c;基于Vue.js和WebSocket技术。这个项目适合初学者学习前端实时数据处理&#xff0c;也能为你的技术博客或作品集增添亮点&#xff01;通过这个教程&#xff0c;你将学会如何使用WebSocket实现实时…

leecode100——接雨水

题目 双指针 思路1 使用参数存储从左往右&#xff08;从右往左同理&#xff09;遍历时的最高的柱子&#xff0c; 然后移动左右的指针&#xff0c;每次移动左右指针中偏向小的&#xff0c; 如果当前指针指的柱子小于最高的柱子&#xff0c;就会存在接到水。 思路2 把水看作柱子&…

复古胶片风格街拍人像Lr调色教程,手机滤镜PS+Lightroom预设下载!

调色教程复古胶片风格街拍人像 Lightroom 调色&#xff0c;通过模拟经典胶片相机的色彩科学&#xff0c;为现代数码照片注入怀旧韵味。这种调色手法注重低饱和度色彩、柔和的高光过渡和丰富的暗部细节&#xff0c;配合适度的颗粒感&#xff0c;营造出时光沉淀的质感。特别适合街…

Linux的gpio子系统

GPIO其实也是某个pin的功能之一。上一小节讲解了 pinctrl 子系统&#xff0c;pinctrl 子系统重点是设置 PIN(有的 SOC 叫做 PAD)的复用和电气属性&#xff0c;如果 pinctrl 子系统将一个 PIN 复用为 GPIO 的话&#xff0c;那么接下来就要用到 gpio 子系统了。gpio 子系统顾名思…

VC++ CPU指令集检测工具实现原理

&#x1f4c8; VC CPU指令集检测工具实现原理 例图&#xff1a;&#x1f9e0; 1. 核心原理&#xff1a;CPUID指令 // 使用CPUID指令获取CPU信息 int cpuInfo[4] { -1 }; __cpuid(cpuInfo, 0); // 调用CPUID指令 int nIds cpuInfo[0]; // 获取最大标准功能号CPUID指令工作流程…

大模型微调理论、实战:LLaMA-Factory、Unsloth

概述 微调&#xff0c;Fine-Tuning&#xff0c;简称FT&#xff0c;可理解为对LLM的定制&#xff0c;目的是增强专业领域知识&#xff0c;并优化特定任务的性能。通过在特定数据集上微调一个预训练模型&#xff0c;可实现&#xff1a; 更新知识&#xff1a;引入新的领域专属信…

【LCA 树上倍增】P9245 [蓝桥杯 2023 省 B] 景区导游|普及+

本文涉及知识点 树上倍增 P9245 [蓝桥杯 2023 省 B] 景区导游 题目描述 某景区一共有 NNN 个景点&#xff0c;编号 111 到 NNN。景点之间共有 N−1N-1N−1 条双向的摆渡车线路相连&#xff0c;形成一棵树状结构。在景点之间往返只能通过这些摆渡车进行&#xff0c;需要花费…

基于Python+Streamlit的旅游数据分析与预测系统:从数据可视化到机器学习预测的完整实现

&#x1f3de;️ 基于PythonStreamlit的旅游数据分析与预测系统&#xff1a;从数据可视化到机器学习预测的完整实现 &#x1f4dd; 前言 在大数据时代&#xff0c;旅游行业的数据分析变得越来越重要。如何从海量的旅游数据中挖掘有价值的信息&#xff0c;并进行准确的销量预测&…

飞算JavaAI全链路实战:智能构建高可用电商系统核心架构

飞算JavaAI全链路实战&#xff1a;智能构建高可用电商系统核心架构 前言&#xff1a;AI编程新时代的电商系统开发范式变革 在当今数字经济时代&#xff0c;电商系统作为企业数字化转型的核心载体&#xff0c;其复杂度和技术要求与日俱增。一个完整的电商系统不仅需要处理商品、…

论文精读(五):面向链接预测的知识图谱表示学习方法综述

笔者链接&#xff1a;扑克中的黑桃A 专栏链接&#xff1a;论文精读 本文关键词&#xff1a;知识图谱; 表示学习; 链接预测; 多元关系; 超关系 引 诸位技术同仁&#xff1a; 本系列将系统精读的方式&#xff0c;深入剖析计算机科学顶级期刊/会议论文&#xff0c;聚焦前沿突破…

Roo Code之自定义指令(Custom Instructions),规则(Rules)

在Roo Code 中&#xff0c;Custom Instructions 可以通过Instructions 设定和Rules 规则文件实现。什么是Custom Instructions&#xff1f; 自定义指令(Custom Instructions)定义了超出Roo基本角色定义范围的具体行为、偏好和约束。示例包括编码风格、文档标准、测试要求和工作…

9/8我是ai大师

一、变量定义部分&#xff08;理解程序的 "记忆"&#xff09;c运行/* USER CODE BEGIN PV */ static uint8_t last_button_state 1; // 初始为高电平&#xff08;未按下&#xff09; static uint8_t device_mode 0; // 设备模式&#xff1a;0LD1, 1LD3, 2蜂鸣器, 3…