快来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())] # 初始化一个栈,元素为当前处理的行数、已经放…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...

