快来get策略模式,告别编程困惑,轻松变身编程高手✨

🎬 江城开朗的豌豆:个人主页
🔥 个人专栏 :《 VUE 》 《 javaScript 》
📝 个人网站 :《 江城开朗的豌豆🫛 》
⛺️ 生活的理想,就是为了理想的生活 !
目录
⭐ 专栏简介
📘 文章引言
一、策略模式是什么
二、使用
三、应用场景
⭐ 写在最后
⭐ 专栏简介
欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、刚刚开始学习前端的读者们打造的。无论你是初学者还是有一些基础的开发者,我们都会在这里为你提供一个系统而又亲切的学习平台。我们以问答形式更新,为大家呈现精选的前端知识点和最佳实践。通过深入浅出的解释概念,并提供实际案例和练习,让你逐步建立起一个扎实的基础。无论是HTML、CSS、JavaScript还是最新的前端框架和工具,我们都将为你提供丰富的内容和实用技巧,帮助你更好地理解并运用前端开发中的各种技术。
同时,我们也会关注最新的前端趋势和发展动态。随着Web技术的不断演进,前端开发也在不断推陈出新。我们会及时介绍最新的前端框架、工具和技术,使你能够站在前沿,与时俱进。通过掌握最新的前端技术,你将能够在竞争激烈的Web开发领域中有更大的竞争力。
📘 文章引言
一、策略模式是什么
策略模式(Strategy Pattern)指的是定义一系列的算法,把它们一个个封装起来,目的就是将算法的使用与算法的实现分离开来
一个基于策略模式的程序至少由两部分组成:
- 策略类,策略类封装了具体的算法,并负责具体的计算过程
- 环境类Context,Context 接受客户的请求,随后 把请求委托给某一个策略类
二、使用
举个例子,公司的年终奖是根据员工的工资和绩效来考核的,绩效为A的人,年终奖为工资的4倍,绩效为B的人,年终奖为工资的3倍,绩效为C的人,年终奖为工资的2倍
若使用if来实现,代码则如下:
var calculateBouns = function(salary,level) {if(level === 'A') {return salary * 4;}if(level === 'B') {return salary * 3;}if(level === 'C') {return salary * 2;}
};
// 调用如下:
console.log(calculateBouns(4000,'A')); // 16000
console.log(calculateBouns(2500,'B')); // 7500
从上述可有看到,函数内部包含过多if...else,并且后续改正的时候,需要在函数内部添加逻辑,违反了开放封闭原则
而如果使用策略模式,就是先定义一系列算法,把它们一个个封装起来,将不变的部分和变化的部分隔开,如下:
var obj = {"A": function(salary) {return salary * 4;},"B" : function(salary) {return salary * 3;},"C" : function(salary) {return salary * 2;}
};
var calculateBouns =function(level,salary) {return obj[level](salary);
};
console.log(calculateBouns('A',10000)); // 40000
上述代码中,obj对应的是策略类,而calculateBouns对应上下通信类
又比如实现一个表单校验的代码,常常会像如下写法:
var registerForm = document.getElementById("registerForm");
registerForm.onsubmit = function(){if(registerForm.userName.value === '') {alert('用户名不能为空');return;}if(registerForm.password.value.length < 6) {alert("密码的长度不能小于6位");return;}if(!/(^1[3|5|8][0-9]{9}$)/.test(registerForm.phoneNumber.value)) {alert("手机号码格式不正确");return;}
}
上述代码包含多处if语句,并且违反了开放封闭原则,如果应用中还有其他的表单,需要重复编写代码
此处也可以使用策略模式进行重构校验,第一步确定不变的内容,即策略规则对象,如下:
var strategy = {isNotEmpty: function(value,errorMsg) {if(value === '') {return errorMsg;}},// 限制最小长度minLength: function(value,length,errorMsg) {if(value.length < length) {return errorMsg;}},// 手机号码格式mobileFormat: function(value,errorMsg) {if(!/(^1[3|5|8][0-9]{9}$)/.test(value)) {return errorMsg;}}
};
然后找出变的地方,作为环境类context,负责接收用户的要求并委托给策略规则对象,如下Validator类:
var Validator = function(){this.cache = []; // 保存效验规则
};
Validator.prototype.add = function(dom,rule,errorMsg) {var str = rule.split(":");this.cache.push(function(){// str 返回的是 minLength:6 var strategy = str.shift();str.unshift(dom.value); // 把input的value添加进参数列表str.push(errorMsg); // 把errorMsg添加进参数列表return strategys[strategy].apply(dom,str);});
};
Validator.prototype.start = function(){for(var i = 0, validatorFunc; validatorFunc = this.cache[i++]; ) {var msg = validatorFunc(); // 开始效验 并取得效验后的返回信息if(msg) {return msg;}}
};
通过validator.add方法添加校验规则和错误信息提示,使用如下:
var validateFunc = function(){var validator = new Validator(); // 创建一个Validator对象/* 添加一些效验规则 */validator.add(registerForm.userName,'isNotEmpty','用户名不能为空');validator.add(registerForm.password,'minLength:6','密码长度不能小于6位');validator.add(registerForm.userName,'mobileFormat','手机号码格式不正确');var errorMsg = validator.start(); // 获得效验结果return errorMsg; // 返回效验结果
};
var registerForm = document.getElementById("registerForm");
registerForm.onsubmit = function(){var errorMsg = validateFunc();if(errorMsg){alert(errorMsg);return false;}
}
上述通过策略模式完成表单的验证,并且可以随时调用,在修改表单验证规则的时候,也非常方便,通过传递参数即可调用
三、应用场景
从上面可以看到,使用策略模式的优点有如下:
- 策略模式利用组合,委托等技术和思想,有效的避免很多if条件语句
- 策略模式提供了开放-封闭原则,使代码更容易理解和扩展
- 策略模式中的代码可以复用
策略模式不仅仅用来封装算法,在实际开发中,通常会把算法的含义扩散开来,使策略模式也可以用来封装 一系列的“业务规则”
只要这些业务规则指向的目标一致,并且可以被替换使用,我们就可以用策略模式来封装它们
⭐ 写在最后
请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.
✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式
✅ 认为我部分代码过于老旧,可以提供新的API或最新语法
✅ 对于文章中部分内容不理解
✅ 解答我文章中一些疑问
✅ 认为某些交互,功能需要优化,发现BUG
✅ 想要添加新功能,对于整体的设计,外观有更好的建议
最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!
相关文章:
快来get策略模式,告别编程困惑,轻松变身编程高手✨
🎬 江城开朗的豌豆:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 📝 个人网站 :《 江城开朗的豌豆🫛 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 ⭐ 专栏简介 📘 文章引言 一…...
UPS负载箱的工作原理是什么?
UPS负载箱(Uninterruptible Power Supply Load Bank)内部包含一组电阻器,通过调节电阻值来模拟不同负载条件。当UPS供电时,电阻器会吸收一定的电能,从而模拟实际负载对UPS的需求。UPS负载箱配备了控制系统,…...
深度学习八股文: 模型训练全过程及各阶段的原因
深度学习模型的训练全过程通常包括以下步骤: 数据准备: 首先,需要准备用于训练的数据集。数据集应包含输入特征(通常是数值或图像数据)和相应的目标标签。数据通常需要被分为训练集、验证集和测试集,以便评…...
CY3-NHS ester良好的光稳定性介绍1032678-38-8
CY3-NHS ester通常表现出良好的光稳定性,这使得它在长时间的荧光成像和实验中非常有用。以下是关于CY3-NHS ester良好光稳定性的一些介绍: 1.抗光漂白性能:CY3-NHS ester通常对光漂白表现出相对高的抵抗力。这意味着在持续激发下,…...
大厂秋招真题【贪心】美团20230826秋招T2-小美的数组重排
文章目录 【贪心】美团2023秋招-小美的数组重排题目描述与示例题目描述输入描述输出描述示例输入输出 说明 解题思路代码PythonJavaC时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 【贪心】美团2023秋招-小美的数组重排 题目描述与示例 题目描述 小美有两个长度为n…...
UnitTest框架的使用
文章目录 一、UnitTest框架是什么?二、UnitTest核心要素三、TestCase四、TestSuite & TestRunner 一、UnitTest框架是什么? UnitTest框架是python自带的一个单元测试框架,主要用它来做单元测试,它有以下特点: 能…...
软件开发项目文档系列之四如何成功撰写一份引人注目的投标文件
目录 前言1 分析招标文件1.1 投标的基础要求分析1.2 投标重点要求分析1.3 评分标准分析1.4 技术需求分析 2 撰写完整的投标文件2.1 明确文件用途2.2 提供评分指引2.3 内容完整重点突出2.4 重视图表和图示 3 认真检查和经验积累3.1 深入的准备3.2 反复检查3.3 咨询和确认3.4 积累…...
Django设置跨域
1, 安装 pip install django-cors-headers 2, 添加应用 INSTALLED_APPS (...corsheaders,... ) 3, 中间层设置 MIDDLEWARE [corsheaders.middleware.CorsMiddleware,... ] 4, 添加白名单 # CORS CORS_ORIGIN_WHITELIST (127.0.0.1:8080,localhost:8080,www.meiduo.si…...
基于Python3的Scapy构造DNS报文
一:DNS协议 DNS(Domain Name System)协议是计算机网络中的一种基础协议,它用于将域名(如www.baidu.com)转换为IP地址(如192.168.0.1),从而实现计算机之间的通信。 DNS 分…...
Jupyter Notebook修改默认浏览器方法
Jupyter Notebook修改默认浏览器方法 Create a Jupyter Notebook Config file jupyter notebook --generate-config打开配置文件.jupyter/jupyter_notebook_config.py找到c.NotebookApp.browser 改成只向自己喜欢的浏览器路径’,这里给出选择google浏览器方法&…...
云计算系统与传统计算系统的比较
随着技术的不断发展,云计算系统逐渐成为了企业和个人使用的主要计算方式之一。然而,很多人对云计算系统与传统计算系统之间的区别和相似之处还存在一些疑惑。本文将以云计算系统和传统计算系统为方向,探讨它们之间的异同点。 首先࿰…...
使用GoogleNet网络实现花朵分类
一.数据集准备 新建一个项目文件夹GoogleNet,并在里面建立data_set文件夹用来保存数据集,在data_set文件夹下创建新文件夹"flower_data",点击链接下载花分类数据集https://storage.googleapis.com/download.tensorflow.org/exampl…...
STM32之Bootloader、USB、IAP/DFU下载
STM32 IAP应用开发——通过内置DFU实现USB升级(方式2) STM32 IAP应用开发——通过内置DFU实现USB升级(方式1) STM32程序下载4:通过STM32CubePro-USB下载 STM32程序下载3:通过STM32CubePro-UART下载 STM…...
解决 Element-ui中 表格(Table)使用 v-if 条件控制列显隐时数据展示错乱的问题
本文 Element-ui 版本 2.x 问题 在 el-table-column 上需根据不同 v-if 条件来控制列显隐时,就会出现列数据展示错乱的情况(要么 A 列的数据显示在 B 列上,或者后端返回有数据的但是显示的为空),如下所示。 <tem…...
Android JNI笔记
JNI、java native interface 。可以实现Java和C、C之间的调用。 在Android开发中是必须要掌握的内容。 在应用开发中,编写JNI代码的注册可分为动态注册和静态注册 动态注册: 声明好方法、注意这些签名 在JNI_OnLoad中进行注册。 static const JNINativ…...
Web开发中会话跟踪的隐藏表单字段(隐藏input)方法
隐藏表单字段是一种会话跟踪方法,通过在HTML表单中添加一个隐藏字段来存储会话标识符。 这样,每次用户提交表单时,会话标识符将与请求一起发送到服务器,以便服务器可以跟踪用户的会话状态。 以下是一个隐藏表单字段的示例&#…...
线性代数相关笔记
线性基 导入 线性基,顾名思义,就是一个包含数字最少的集合,使得原集合中的任何数都能用线性基中的元素表示。 集合中的元素满足一些性质: 原集合中的任意元素都可以用线性基中的若干元素的异或和表示线性基中任意数异或和不为…...
【SA8295P 源码分析 (四)】69 - Android 侧添加支持 busybox telnetd 服务
【SA8295P 源码分析】69 - Android 侧添加支持 busybox telnetd 服务 一、下载 busybox-1.36.1.tar.bz2 源码包二、编译 busybox 源码三、将编译后的 busybox 打包编入Android 镜像中系列文章汇总见:《【SA8295P 源码分析 (四)】网络模块 文章链接汇总 - 持续更新中》 本文链接…...
如何开发一个 Safari 插件
本文字数:2493字 预计阅读时间:15分钟 由于常用浏览器是Safari,而Safari浏览器的插件比不上Chrome,所以就有了自己开发常用的Safari插件的想法。 打算开发当前页面生成二维码的Extension,因为网络原因,AirD…...
n皇后问题,不用递归
注释如下: class Solution:def totalNQueens(self, n: int) -> int:if n < 1: # 如果 n 小于 1,直接返回 0return 0count 0 # 初始化解的个数为 0stack [(0, set(), set(), set())] # 初始化一个栈,元素为当前处理的行数、已经放…...
网络安全实战:熊猫烧香病毒行为分析与手工清除指南
1. 熊猫烧香病毒的前世今生 2006年底,一只"熊猫"突然在互联网上掀起轩然大波。这个名为"熊猫烧香"的病毒以其独特的感染标志——被篡改的文件图标变成熊猫举着三炷香的图案,迅速席卷全国。我当时在一家小型IT公司做技术支持&#x…...
魔兽争霸3现代难题终结者:WarcraftHelper一站式解决方案
魔兽争霸3现代难题终结者:WarcraftHelper一站式解决方案 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 还在为魔兽争霸3在现代电脑上的各…...
使用FFmpeg高效实现MKV多语言字幕动态封装与同步技术
1. 为什么MKV格式是字幕封装的最佳选择 每次看到电影里那些硬编码在画面上的字幕就头疼——想换个语言版本?没戏。MKV(Matroska)这种封装格式简直就是为多语言字幕而生的,它允许我们把字幕作为独立轨道嵌入视频文件,就…...
014集——CSV格式坐标批量导入CAD图纸(C#二次开发高效技巧)
1. CSV坐标批量导入CAD的实战价值 每次遇到需要把几百个坐标点画到CAD图纸的情况,你是不是还在手动一个个输入?我在某次水利工程测绘项目中,就亲眼见过同事对着纸质表格敲了整整两天坐标。其实用C#二次开发配合CSV文件,20秒就能搞…...
MySQL入门实战:从零学写SQL,口语化生动讲解,新手也能轻松学会
MySQL从零开始完全教程|小白入门手把手教学生动口语化|7280字真实干货 嘿,朋友!别划走——你点开的不是那种“先讲ACID再扯CAP理论”的天书,也不是满屏SELECT * FROM sys.schema_table_statistics_with_buffer的炫技P…...
Qwen3-4B镜像快速入门:免Python免CUDA,浏览器打开就能聊
Qwen3-4B镜像快速入门:免Python免CUDA,浏览器打开就能聊 1. 为什么选择这个镜像? 想象一下:你刚拿到一台新电脑,想体验最新的大语言模型,但发现需要先安装Python、配置CUDA、解决各种依赖冲突...这个过程…...
JAVA电子合同电子签名小程序系统源码的难点
在开发 JAVA电子合同电子签名小程序系统源码 时,需攻克多语言支持、高并发处理、防作弊机制、复杂业务逻辑、法律合规性及跨平台兼容性六大核心难点。以下是具体分析及解决方案:1. 多语言支持与国际化(i18n)难点:系统需…...
S32DS中集成RTD 扩展包
S32系列MCU在进行软件开发时,我们可以选择使用S32DS的IDE开发环境,在使用的时候我们通常还需要RTD的包,那么如何把RTD的扩展包集成到S32DS中呢,今天我们就来详细的说明一下这个步骤,方便大家参考。 首先在下载安装包的…...
GD32F105RBT6 IAP实战:手把手教你合并BootLoader与APP的bin文件(告别两次烧录)
GD32F105RBT6 IAP实战:从双文件烧录到单文件固件整合的终极方案 在嵌入式产品量产过程中,每次烧录都需要处理BootLoader和APP两个独立的bin文件,不仅效率低下,还增加了生产环节出错的风险。想象一下,当生产线需要烧录上…...
吐血总结!Uni-app / 微信小程序 iOS 与 Android 经典兼容性踩坑实录
跨平台开发界流传着一句名言:“Write once, run anywhere”,但在实际的 Uni-app 和微信小程序开发中,我们往往体会到的是 “Write once, debug everywhere”。由于 iOS(通常基于 WebKit/WKWebView)和 Androidÿ…...

