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

【前端设计模式】之策略模式

概述

在前端开发中,我们经常会遇到需要根据不同的条件或情况来执行不同的算法或行为的情况。这时,策略模式就能派上用场。策略模式是一种行为型设计模式,它将不同的算法封装成独立的策略对象,使得这些算法可以互相替换,而不影响客户端代码。这种灵活性和可扩展性使得策略模式在前端开发中得到广泛应用。

前端应用示例

1. 抽象策略类

假设我们正在开发一个电商网站,在商品详情页需要根据不同的促销活动来计算商品的折扣价格。我们可以使用策略模式来处理这种情况。

首先,我们定义一个抽象策略类 DiscountStrategy,其中包含一个抽象方法 calculateDiscount 用于计算折扣价格。

class DiscountStrategy {calculateDiscount(price) {// 抽象方法,具体实现由子类实现}
}

然后,我们创建具体的策略类,如 FixedDiscountStrategy(固定折扣)和 PercentageDiscountStrategy(百分比折扣),它们分别实现了 calculateDiscount 方法来计算不同的折扣价格。

class FixedDiscountStrategy extends DiscountStrategy {calculateDiscount(price) {return price - 10; // 固定折扣10元}
}class PercentageDiscountStrategy extends DiscountStrategy {calculateDiscount(price) {return price * 0.8; // 百分比折扣,打八折}
}

最后,在商品详情页的代码中,根据不同的促销活动选择合适的策略对象,并调用其 calculateDiscount 方法来计算商品的折扣价格。

const price = 100; // 商品原价let discountStrategy;if (isFixedDiscount) {discountStrategy = new FixedDiscountStrategy();
} else if (isPercentageDiscount) {discountStrategy = new PercentageDiscountStrategy();
}const discountedPrice = discountStrategy.calculateDiscount(price);

这样,当需要新增或修改促销策略时,只需创建或修改相应的策略对象即可,而不需要修改商品详情页的代码。这提高了代码的可维护性和可扩展性。

2. 优化if else代码

当需要根据不同的条件执行不同的代码逻辑时,使用策略模式可以优化if else代码。下面是一个前端策略模式优化if else代码的示例:

// 定义策略对象
const strategies = {option1: function() {// 执行选项1的逻辑},option2: function() {// 执行选项2的逻辑},option3: function() {// 执行选项3的逻辑}
};// 定义上下文对象
const context = {executeStrategy: function(strategyName) {const strategy = strategies[strategyName];if (strategy) {strategy();} else {// 处理未知策略的情况}}
};// 使用示例
context.executeStrategy('option1'); // 执行选项1的逻辑
context.executeStrategy('option2'); // 执行选项2的逻辑
context.executeStrategy('option3'); // 执行选项3的逻辑

在上面的示例中,我们首先定义了一个包含不同策略函数的strategies对象。然后,我们定义了一个上下文对象context,其中包含了一个executeStrategy方法,该方法接受一个策略名称作为参数,并根据该名称执行相应的策略函数。

3. 实现加减乘除
// 定义一个策略对象
const strategies = {add: function(a, b) {return a + b;},subtract: function(a, b) {return a - b;},multiply: function(a, b) {return a * b;},divide: function(a, b) {return a / b;}
};// 定义一个执行操作的函数
function executeOperation(operation, a, b) {if (strategies.hasOwnProperty(operation)) {return strategies[operation](a, b);} else {throw new Error('Unsupported operation');}
}// 使用示例
console.log(executeOperation('add', 5, 3)); // 输出: 8
console.log(executeOperation('subtract', 5, 3)); // 输出: 2
console.log(executeOperation('multiply', 5, 3)); // 输出: 15
console.log(executeOperation('divide', 6, 2)); // 输出: 3
console.log(executeOperation('power', 2, 3)); // 抛出错误:Unsupported operation

在上面的示例中,我们定义了一个strategies对象,它包含了不同的操作(add、subtract、multiply和divide)作为属性,并且每个属性对应一个执行该操作的函数。然后,我们定义了一个executeOperation函数,它接受一个操作名称和两个参数,并根据操作名称调用相应的策略函数来执行操作。

通过使用策略模式,我们可以轻松地添加新的操作或修改现有的操作,而不需要修改executeOperation函数的代码。这样可以提高代码的可维护性和可扩展性。

4. 表单验证

在表单验证中,可以使用策略模式来定义不同的验证规则,并根据不同的规则来执行相应的验证操作。

const validationStrategies = {required: function(value) {return value !== '';},email: function(value) {return /^[^\s@]+@[^\s@]+.[^\s@]+$/.test(value);},minLength: function(value, length) {return value.length >= length;}
};function validateField(value, rules) {for (let rule of rules) {const [strategy, ...params] = rule.split(':');if (validationStrategies.hasOwnProperty(strategy)) {const isValid = validationStrategies[strategy](value, ...params);if (!isValid) {return false;}} else {throw new Error('Unsupported validation strategy');}}return true;
}// 使用示例
const emailValue = 'test@example.com';
const emailRules = ['required', 'email'];
console.log(validateField(emailValue, emailRules)); // 输出: trueconst passwordValue = '123';
const passwordRules = ['required', 'minLength:6'];
console.log(validateField(passwordValue, passwordRules)); // 输出: false
5. 动态组件渲染

在动态组件渲染中,可以使用策略模式来根据不同的条件或状态选择性地渲染不同的组件。

const componentStrategies = {home: function() {return <HomeComponent />;},profile: function() {return <ProfileComponent />;},settings: function() {return <SettingsComponent />;}
};function renderComponent(page) {if (componentStrategies.hasOwnProperty(page)) {return componentStrategies[page]();} else {throw new Error('Unsupported page');}
}// 使用示例
const currentPage = 'profile';
const component = renderComponent(currentPage);
ReactDOM.render(component, document.getElementById('app'));
6. 数据转换和格式化

在数据转换和格式化中,可以使用策略模式来定义不同的转换规则,并根据不同的规则来执行相应的转换操作。

const formatStrategies = {currency: function(value) {return `$${value.toFixed(2)}`;},percentage: function(value) {return `${(value * 100).toFixed(2)}%`;},uppercase: function(value) {return value.toUpperCase();}
};function formatData(data, format) {if (formatStrategies.hasOwnProperty(format)) {return formatStrategies[format](data);} else {throw new Error('Unsupported format');}
}// 使用示例
const amount = 10.5;
console.log(formatData(amount, 'currency')); // 输出: $10.50const rate = 0.75;
console.log(formatData(rate, 'percentage')); // 输出: 75.00%const name = 'john doe';
console.log(formatData(name, 'uppercase')); // 输出: JOHN DOE

这些只是前端策略模式的一些常见应用场景,实际上,策略模式可以应用于任何需要根据不同的条件或情况来执行不同操作的场景。

优缺点

优点

  • 可扩展性:新增或修改算法变得简单,只需添加或修改相应的策略对象即可,而不需要修改客户端代码。
  • 可维护性:代码结构更清晰、可读性更高,易于维护和理解。
  • 可复用性:策略对象可以在不同的场景中被复用,避免了重复编写相似的代码。
  • 松耦合:客户端与具体的策略对象解耦,客户端只需要知道如何使用策略对象即可。

缺点

  • 增加了类和对象的数量:引入了多个策略对象会增加类和对象的数量,可能会增加系统复杂度。
  • 客户端需要了解所有的策略:客户端需要知道所有可用的策略,并选择合适的策略进行使用。

总结

前端设计模式之策略模式是一种强大而灵活的模式,在处理不同算法或行为时能够提供良好的解决方案。通过将不同的算法封装成独立的策略对象,策略模式使得代码更加可维护、可扩展和可复用。在前端开发中,合理应用策略模式能够提高代码质量和开发效率。

相关文章:

【前端设计模式】之策略模式

概述 在前端开发中&#xff0c;我们经常会遇到需要根据不同的条件或情况来执行不同的算法或行为的情况。这时&#xff0c;策略模式就能派上用场。策略模式是一种行为型设计模式&#xff0c;它将不同的算法封装成独立的策略对象&#xff0c;使得这些算法可以互相替换&#xff0…...

JUC包(面试常问)

1. Callable接口 类似于Runnable接口&#xff0c;Runnable描述的任务&#xff0c;不带返回值&#xff1b;Callable描述的任务带返回值。 public class Test {//创建线程&#xff0c;计算12...1000public static void main(String[] args) throws ExecutionException, Interru…...

文字处理工具Word mac软件特点

Microsoft Word mac是一款文字处理软件。它是 Microsoft office 套件的一部分&#xff0c;已广泛用于创建、编辑和格式化文本文档。 Word mac软件特点 改进的协作工具&#xff1a;使用 Microsoft Word 2021&#xff0c;多个用户可以同时处理一个文档&#xff0c;从而更轻松地与…...

把 Windows 11 装进移动硬盘:Windows 11 To Go

本篇文章聊聊如何制作一个可以“说带走就带走”的 Windows 操作系统&#xff0c;将 Windows11 做成能够放在 U 盘或者移动硬盘里的 WinToGo “绿色软件”。 写在前面 在《开源的全能维护 U 盘工具&#xff1a;Ventoy》这篇文章的最后&#xff0c;我提到了一个关键词 “WinToG…...

11、pytest断言预期异常

官方用例 # content of test_exception_zero.py import pytestdef test_zero_division():with pytest.raises(ZeroDivisionError):1/0# content of test_exception_runtimeerror.py import pytestdef test_recursion_depth():with pytest.raises(RuntimeError) as excinfo:def…...

Vue之数据绑定

在我们Vue当中有两种数据绑定的方法 1.单向绑定 2.双向绑定 让我为大家介绍一下吧&#xff01; 1、单向绑定(v-bind) 数据只能从data流向页面 举个例子&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"…...

druid在没有web的项目中如何查看监控

&#xff08;1&#xff09;在这个网址下载druidStat.bat文件https://github.com/alibaba/druid/blob/master/core/src/main/scripts/druidStat.bat druidStat.bat文件内容如下&#xff1a; echo offset _RUNJAVA"%JAVA_HOME%\bin\java.exe" set _TOOLSJAR"%JA…...

游戏被攻击该怎么办?游戏盾该如何使用,游戏盾如何防护攻击

随着Internet互联网络带宽的增加和多种DDOS黑客工具的不断发布&#xff0c;DDOS拒绝服务攻击的实施越来越容易&#xff0c;DDOS攻击事件正在成上升趋势。出于商业竞争、打击报复和网络敲诈等多种因素&#xff0c;导致很多商业站点、游戏服务器、聊天网络等网络服务商长期以来一…...

【基于openGauss5.0.0简单使用DBMind】

基于openGauss5.0.0简单使用DBMind 一、环境说明二、初始化tpch测试数据三、使用DBMind索引推荐功能四、使用DBMind实现SQL优化功能 一、环境说明 虚拟机&#xff1a;virtualbox操作系统&#xff1a;openEuler 20.03 TLS数据库&#xff1a;openGauss-5.0.0DBMind&#xff1a;d…...

[递归回溯]连接卡片最短路径

小游戏 题目描述 一天早上&#xff0c;你起床的时候想&#xff1a;“我编程序这么牛&#xff0c;为什么不能靠这个挣点银子呢&#xff1f;”因此你决定编写一个小游戏。 游戏在一个分割成w * h个长方格子的矩形板上进行。如图所示&#xff0c;每个长方格子上可以有一张游戏…...

初识人工智能,一文读懂强化学习的知识文集(5)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…...

视频封面提取:精准截图,如何从指定时长中提取某一帧图片

在视频制作和分享过程中&#xff0c;一个有吸引力的封面或截图往往能吸引更多的观众点击观看。有时候要在特定的时间段内从视频中提取一帧作为封面或截图。如果每个视频都手动提取的话就会耗费很长时间&#xff0c;那么如何智化能批量提取呢&#xff1f;现在一起来看下云炫AI智…...

Shopify 开源 WebAssembly 工具链 Ruvy

最近,Spotify 开源了Ruvy,一个 WebAssembly 工具链,能够将 Ruby 代码转换为 Wasm 模块。Ruvy 基于ruby.wasm, 用 Rust 实现,提升了性能并简化了 Wasm 模块的执行。 Ruvy 利用了ruby.wasm提供的 Ruby 解释器模块,并使用wasi-vfs (WASI 虚拟文件系统)将其与所有指定的 Rub…...

zxjy008- 项目集成Swagger

Swagger可以生成在线文档&#xff0c;还可以进行接口测试。 1、创建common模块(maven类型) 为了让所有的微服务子子模块都可以使用&#xff0c;可以在guli_parent父工程下面创建公共模块 1.1 在guli_parent父工程下面创建公共模块 配置&#xff1a; groupId&#xff1a;com…...

使用linux CentOS本地部署SQL Server数据库

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;数据结构、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 安装sql server二. 局域网测试连接三. 安装cpolar内网穿透四. 将sqlserver映射…...

理解基于 Hadoop 生态的大数据技术架构

转眼间&#xff0c;一年又悄然而逝&#xff0c;时光荏苒&#xff0c;岁月如梭。当回首这段光阴&#xff0c;不禁感叹时间的匆匆&#xff0c;仿佛只是一个眨眼的瞬间&#xff0c;一年的旅程已成为过去&#xff0c;而如今又到了画饼的时刻了 &#xff01; 基于 Hadoop 生态的大数…...

【Go】Go语言基础内容

变量声明&#xff1a; 变量声明&#xff1a;在Go中&#xff0c;变量必须先声明然后再使用。声明变量使用 var 关键字&#xff0c;后面跟着变量名和类型&#xff0c;如下所示&#xff1a; var age int这行代码声明了一个名为 age 的整数变量。 变量初始化&#xff1a;您可以在声…...

HP-UNIX 系统安全基线 安全加固操作

目录 账号管理、认证授权 账号 ELK-HP-UX-01-01-01 ELK -HP-UX-01-01-02 ELK -HP-UX-01-01-03 ​​​​​​​ ELK-HP-UX-01-01-04 ​​​​​​​ELK-HP-UX-01-01-05 ​​​​​​​口令 ELK-HP-UX-01-02-01 ​​​​​​​ ELK-HP-UX-01-02-02 ​​​​​​​ ELK-HP…...

第九天:信息打点-CDN绕过篇amp;漏洞回链amp;接口探针amp;全网扫描amp;反向邮件

信息打点-CDN绕过篇 cdn绕过文章&#xff1a;https://www.cnblogs.com/qiudabai/p/9763739.html 一、CDN-知识点 1、常见访问过程 1、没有CDN情况下传统访问&#xff1a;用户访问域名-解析服务器IP–>访问目标主机 2.普通CDN&#xff1a;用户访问域名–>CDN节点–>…...

【利用二手车数据进行可视化分析】

利用二手车数据进行可视化分析 查看原始数据去除重复数据需求分析1.统计全国总共有多少量二手车&#xff0c;用KPI图进行展示2.统计安徽总共有多少量二手车&#xff0c;用KPI图进行展示3.统计合肥总共有多少量二手车&#xff0c;用KPI图进行展示4.取最贵的10辆二手车信息&#…...

【金蝶云星空】无发票模块非暂估模式下,期初应付录入

学习目标 学习本内容后&#xff0c;您将掌握如何录入在没发票模块&#xff0c;不启用暂估应付模式下的应付初始化数据 业务背景 本篇我们则进行讲解没发票模块&#xff0c;不启用暂估应付模式下如何录入期初数据。 业务场景有“先开票后入库、已入库未开票、已入库已开票未付…...

程序员副业指南:从技术到变现全攻略

CSDN程序员副业图谱技术文章大纲副业图谱概述副业图谱的定义与背景CSDN平台在程序员副业中的作用副业图谱的核心价值&#xff08;技能变现、职业发展等&#xff09;常见程序员副业类型技术博客与内容创作&#xff08;如CSDN专栏、公众号&#xff09;在线教育与课程开发&#xf…...

MentorBit红外驱动库:裸机与RTOS下的精准时序控制

1. MentorBit-DetectorIR 库概述MentorBit-DetectorIR 是一款专为 MentorBit 红外发射/接收模块设计的嵌入式底层驱动库&#xff0c;其核心定位并非通用红外协议栈&#xff08;如 NEC、RC5 解码&#xff09;&#xff0c;而是面向硬件验证、模块级功能测试与快速原型开发的轻量级…...

如何高效使用SpiecEasi进行微生物网络分析:microeco的完整指南

如何高效使用SpiecEasi进行微生物网络分析&#xff1a;microeco的完整指南 【免费下载链接】microeco An R package for data analysis in microbial community ecology 项目地址: https://gitcode.com/gh_mirrors/mi/microeco 在微生物生态学研究中&#xff0c;构建可靠…...

Intel集成显卡加速PyTorch:从环境搭建到模型训练实战指南

1. 为什么选择Intel集成显卡加速PyTorch&#xff1f; 很多朋友刚接触深度学习时&#xff0c;第一反应都是"得买块N卡"。但你可能不知道&#xff0c;手头的Intel集成显卡也能跑PyTorch&#xff0c;而且效果还不错。我去年给团队配开发机时&#xff0c;就专门测试过Int…...

ABB机器人X6-WAN口多协议共存实战:NFS、Socket、RobotStudio与Profinet如何和谐共处?

ABB机器人X6-WAN口多协议共存实战&#xff1a;NFS、Socket、RobotStudio与Profinet如何和谐共处&#xff1f; 在工业自动化领域&#xff0c;ABB机器人系统的网络配置一直是工程师们关注的焦点。特别是当我们需要在单个X6-WAN口上同时运行NFS文件传输、Socket通信、RobotStudio远…...

如何用Dify API和GPT-4o高效识别图片?附避坑指南

如何用Dify API和GPT-4o高效识别图片&#xff1f;附避坑指南 在当今数字化时代&#xff0c;图片识别技术已成为众多应用场景中的核心需求。从电商平台的商品自动分类到社交媒体内容审核&#xff0c;再到医疗影像分析&#xff0c;高效准确的图片识别能力正变得越来越重要。Dify作…...

DeepFaceLive实时面部交换技术完全教程

DeepFaceLive实时面部交换技术完全教程 还在为视频会议和直播效果发愁吗&#xff1f;想不想在下次Zoom会议中突然变身成你喜欢的明星&#xff1f;DeepFaceLive这款神奇的工具能让你的面部特效梦想成真&#xff01;今天我们就来聊聊这个让无数内容创作者痴迷的实时面部交换技术…...

Linux日志高效搜索:从基础grep到journalctl实战技巧

1. Linux日志搜索&#xff1a;运维工程师的必备技能 每次服务器出现异常&#xff0c;第一反应是什么&#xff1f;没错&#xff0c;就是查日志。作为在Linux系统摸爬滚打多年的老运维&#xff0c;我见过太多新手面对海量日志时的手足无措。其实日志排查就像破案&#xff0c;关键…...

丁二酸酯PEG氨基叔丁氧羰基,NHBoc-PEG-SA,可与胺基、羟基等基团发生缩合反应

一.名称英文名称&#xff1a;SA-PEG-NHBoc&#xff0c;Succinic Acid-PEG-NHBoc&#xff0c;NHBoc-PEG-SA&#xff0c;NHBoc-PEG-Succinic Acid中文名称&#xff1a;丁二酸酯聚乙二醇氨基叔丁氧羰基&#xff0c;丁二酸酯PEG氨基叔丁氧羰基分子量&#xff1a;1k&#xff0c;2k&a…...