策略模式,一种广泛应用于各种情况的设计模式(设计模式与开发实践 P5)
文章目录
- 策略模式
- 实现
- 思想
- 实战 - 表单
策略模式
定义:定义一系列算法,把它们一个个封装起来,并且可以互相替换
例如,我们要计算年终奖,年终奖根据绩效 A、B、C 来计算最终数值
实现
最初我们很容易想到用 分支 if 来解决这个问题,如果绩效 = A 则工资 x 2,如果绩效 = B 则工资 x 3
如果经常使用这样的分支结构,你会发现代码耦合度很高,很容易就出现一大坨代码堆砌在一起,只是 x 2 或者 x 3 不足以形成难以维护的结构,但如果不是 x 2 而是一个复杂的代码块,我们显然会想到封装里面的代码!
var performA = function (salary) {return salary * 4;
};var performB = function (salary) {return salary * 3;
};var performC = function (salary) {return salary * 2;
};var calcBonus = function (level, salary) {if (level == "A") {return performA(salary);} else if (level == "B") {return performB(salary);} else if (level == "C") {return performC(salary);}
};
是的,虽然我们优化了代码,但没好到哪去,如果要添加一个 D 级,我们还是得堆砌代码
让我们来看看策略模式怎么做吧,策略模式让 策略 被定义和封装,且可以相互替换
这就是最终代码了,但在 javascript 中实现策略相较 C# 或者其他语言来说要容易的多,在下面举例了 C# 代码
var strategies = {A: function (salary) {return salary * 4;},B: function (salary) {return salary * 3;},C: function (salary) {return salary * 2;},
};var calculateBonus = function (level, salary) {return strategies[level](salary);
};
需要注意的是 strategies 对象存储的 3 个匿名函数, Func 类是用来存储函数的,需要一定的函数工具类基础
掌握这样的思想以后,试着把 {"A", (salary) => salary * 4}
解耦出去动态添加即可~
using System;
using System.Collections.Generic;public class Program
{private static Dictionary<string, Func<double, double>> strategies = new Dictionary<string, Func<double, double>>(){{"A", (salary) => salary * 4},{"B", (salary) => salary * 3},{"C", (salary) => salary * 2}};private static double CalculateBonus(string level, double salary){return strategies[level](salary);}public static void Main(string[] args){string level = "A";double salary = 1000;double bonus = CalculateBonus(level, salary);Console.WriteLine("Bonus: " + bonus);}
}
思想
通过上面的重构:
- 消除了大片的分支语句
- 计算奖金的逻辑不再存储在 CalculateBonus 里了,而是分布在策略对象里
- 策略对象只负责计算奖金
- 策略对象之间可以相互替换
实战 - 表单
这是一种尤为常见的表单验证方式,相信绝大多数前端程序员这样写过
显然能发现,这里的 if 堆砌过多,不仅如此,内部的 逻辑 相比上面的代码也更复杂
var registerForm = function (form) {if (form.username.value === "") {alert("用户名不能为空");return false;}if (form.password.value.length < 6) {alert("密码长度不能少于6位");return false;}if (!/(^1[3|5|8][0-9]{9}$)/.test(form.phoneNumber.value)) {alert("手机号码格式不正确");return false;}
};
我们可以用策略模式的思路来实现类似这样的代码,这样当我们需要增加验证步骤时,只需要添加策略内容即可:
var validateStrategy = {isNotEmpty: function (form) {if (form.name === "") {return "用户名不能为空";}return "";},minLength: function (form) {if (form.password.length < 6) {return "密码长度不能少于6位";}return "";},isMobile: function (form) {if (!/(^1[3|5|8][0-9]{9}$)/.test(form.phone)) {return "手机号码格式不正确";}return "";},
};var validate = function (form) {for (let func in validateStrategy) {if (validateStrategy.hasOwnProperty(func) &&typeof validateStrategy[func] === "function") {var msg = validateStrategy[func](form);if (msg != "") return false;}}return true;
};
相关文章:
策略模式,一种广泛应用于各种情况的设计模式(设计模式与开发实践 P5)
文章目录 策略模式实现思想实战 - 表单 策略模式 定义:定义一系列算法,把它们一个个封装起来,并且可以互相替换 例如,我们要计算年终奖,年终奖根据绩效 A、B、C 来计算最终数值 实现 最初我们很容易想到用 分支 if…...
90. 子集 II
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。 示例 1: 输入:nums [1,2,2] 输出…...
Intel汇编语言程序设计(第7版)第四章编程练习题答案
1. 大端序转成小端序 .386 .model flat, stdcall option casemap:none include windows.inc include kernel32.inc includelib kernel32.lib include user32.inc includelib user32.lib.stack 4096.data bigEndian BYTE 12h, 34h, 56h, 78h littleEndian DWORD ?Fmt BYTE &…...
EDA(Exploratory Data Analysis)探索性数据分析
EDA(Exploratory Data Analysis)中文名称为探索性数据分析,是为了在特征工程或模型开发之前对数据有个基本的了解。数据类型通常分为两类:连续类型和离散类型,特征类型不同,我们探索的内容也不同。 1. 特征类型 1.1 连续型特征 …...
Python中的多媒体处理库有哪些?
在Python中,有几个常用的多媒体处理库,包括: Pillow - 一个强大的图像处理库,可以进行图像的读取、保存、剪裁、调整大小、滤镜处理等操作。 OpenCV - 一个用于图像和视频处理的开源计算机视觉库,提供了许多图像处理和…...
LeetCode【28. 找出字符串中第一个匹配项的下标】
不要用珍宝装饰自己,而要用健康武装身体 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。 …...
产业互联网开始从简单的概念,逐渐成为可以落地的存在
当流量不再是红利,几乎所有的消费互联网模式开始失效。这一现象,并不仅仅只是体现在流量获取成本的不断增加上,同样还体现在流量激活的难度不断增加上。事实证明,以产业链末端为主要驱动力的发展模式,正在走入到死胡同…...
element-ui tree组件实现在线增删改
这里要实现一个tree 增删改 <!--oracle巡检项--> <template><div class"oracle_instanceType"><el-row type"flex" align"middle" justify"space-between"><iclass"el-icon-s-fold iBox"click&q…...
华为开源自研AI框架昇思MindSpore应用案例:消噪的Diffusion扩散模型
目录 一、环境准备1.进入ModelArts官网2.使用CodeLab体验Notebook实例 二、案例实现构建Diffusion模型位置向量ResNet/ConvNeXT块Attention模块组归一化条件U-Net正向扩散数据准备与处理采样训练过程推理过程(从模型中采样) 本文基于Hugging Face&#x…...
华为CD32键盘使用教程
华为CD32键盘使用教程 用爱发电写的教程! 最后更新时间:2023.9.12 型号:华为有线键盘CD32 基本使用 此键盘在不安装驱动的情况下可以直接使用,但是不安装驱动指纹识别是无法使用的!并且NFC功能只支持华为的部分电脑…...
第三节:在WORD为应用主窗口下关闭EXCEL的操作(2)
【分享成果,随喜正能量】凡事好坏,多半自作自受,既不是神为我们安排,也不是天意偏私袒护。业力之前,机会均等,毫无特殊例外;好坏与否,端看自己是否能应机把握,随缘得度。…...
Layui + Flask | 弹出层(组件篇)(04)
提示:点击阅读原文体验更佳 https://layui.dev/docs/2.8/layer/ 弹出层组件 layer 是 Layui 最古老的组件,也是使用覆盖面最广泛的代表性组件。在实现网页弹出层的首选交互方案,使用的非常频繁。 打开弹层 layer.open(options); 参数 options : 基础属性配置项。打开弹层的核…...
Electron和vue3集成(推荐仅用于开发)
本篇我们仅实现Electron和vue3通过先运行起vue3项目,再将vue3的url地址交由Electron打开的方案,仅由Electron在vue3项目上套一层壳来达到脱离本机浏览器运行目的 1、参考快速上手 | Vue.js搭建起vue3初始项目 npm install -g vue npm install -g vue/c…...
Vue.js和TypeScript:如何完美结合
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...
034:vue项目利用qrcodejs2生成二维码示例
第034个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下,本专栏提供行之有效的源代码示例和信息点介绍,做到灵活运用。 (1)提供vue2的一些基本操作:安装、引用,模板使…...
执行 git remote add github git@github.com:xxxx/testGit.git时,git内部做了啥?
git remote add 往 .git/config 中写入了一个叫 [remote "origin"] 配置 url → 表示该远程名称对应的远程仓库地址fetch 参数分为两部分,以冒号 : 进行分割冒号左边 ☞ 本地仓库文件夹冒号右边 ☞ 远程仓库在本地的副本文件夹 ☞ 往里面添加数据的意思 可…...
Makefile基础
迷途小书童 读完需要 4分钟 速读仅需 2 分钟 1 引言 下面这个 C 语言的代码非常简单 #include <stdio.h>int main() {printf("Hello World!.\n");return 0; } 在 Linux 下面,我们使用下面的命令编译就可以 gcc hello.c -o hello 但是随着项目的变大…...
【PickerView案例08-国旗搭建界面加载数据 Objective-C预言】
一、来看我们第三个案例 1.来看我们第三个关于PickerView的一个案例, 首先呢,我要问大家一下, 咱们这个是几组数据呢, 这是一个pickerView,只不过,它显示的是什么,一个界面, 前面两个案例,都是文字 这个案例,开始有图片了, 总结一下这三个案例: 1)第一个案例…...
2023-09-15力扣每日一题
链接: [LCP 50. 宝石补给](https://leetcode.cn/problems/queens-that-can-attack-the-king/) 题意 略 解: 简单题 模拟 实际代码: int giveGem(vector<int>& gem, vector<vector<int>>& operations) {for(…...
系列七、Nginx负载均衡配置
一、目标 浏览器中访问http://{IP地址}:9002/edu/index.html,浏览器交替打印清华大学8080、清华大学8081. 二、步骤 2.1、在tomcat8080、tomcat8081的webapps中分别创建edu文件夹 2.2、将index.html分别上传至edu文件夹 注意事项:tomcat8080的edu文件…...
Python爬虫(二十)_动态爬取影评信息
本案例介绍从JavaScript中采集加载的数据。更多内容请参考:Python学习指南 #-*- coding:utf-8 -*- import requests import re import time import json#数据下载器 class HtmlDownloader(object):def download(self, url, paramsNone):if url is None:return Noneuser_agent …...
基于 Flink CDC 高效构建入湖通道
本文整理自阿里云 Flink 数据通道负责人、Flink CDC 开源社区负责人, Apache Flink PMC Member & Committer 徐榜江(雪尽),在 Streaming Lakehouse Meetup 的分享。内容主要分为四个部分: Flink CDC 核心技术解析数…...
redis的基础底层篇 zset的详解
一 zset的作用以及结构 1.1 zset作用 redis的zset是一个有序的集合,和普通集合set非常相似,是一个没有重复元素的字符串集合。常用作排行榜等功能,以用户 id 为 value,关注时间或者分数作为 score 进行排序。 1.2 zset的底层结…...
数据分享|R语言逻辑回归、线性判别分析LDA、GAM、MARS、KNN、QDA、决策树、随机森林、SVM分类葡萄酒交叉验证ROC...
全文链接:http://tecdat.cn/?p27384 在本文中,数据包含有关葡萄牙“Vinho Verde”葡萄酒的信息(点击文末“阅读原文”获取完整代码数据)。 介绍 该数据集(查看文末了解数据获取方式)有1599个观测值和12个变量…...
Open3D(C++) 点云旋转的轴角表示法和罗德里格斯公式
目录 一、算法原理1、轴角表示法2、罗德里格斯公式二、代码实现三、结果展示四、相关链接一、算法原理 1、轴角表示法 假设刚体坐标系为B(Oxyz)绕单位向量 ω ⃗ \vec{ω}...
CPU的三级缓存
CPU缓存(Cache Memory)是位于CPU与内存之间的临时存储器,它的容量比内存小的多但是交换速度却比内存要快得多。高速缓存的出现主要是为了解决CPU运算速度与内存读写速度不匹配的矛盾,因为CPU运算速度要比内存读写速度快很多&#…...
pgzrun 拼图游戏制作过程详解(6,7)
6. 检查拼图完成 初始化标记成功的变量Is_Win Is_WinFalse 当鼠标点击小拼图时,判断所有小拼图是否都在正确的位置,并更新Is_Win。 def on_mouse_down(pos,button): # 当鼠标被点击时# 略is_win Truefor i in range(6):for j in range(4):Square S…...
laravel框架 - 集合篇
Laravel Eloquent 通常返回一个集合作为结果,集合包含很多有用的、功能强大的方法。 你可以很方便的对集合进行过滤、修改等操作。 本次教程就一起来看一看集合的常用方法及功能。 你可以使用助手函数 collect 将数组转化为集合。 $data collect([1, 2, 3]); 1…...
[npm]package.json文件
[npm]package.json文件 生成 package.jsonpackage.json 必须属性nameversion 描述信息descriptionkeywordsauthorcontributorshomepagerepositorybugs 依赖配置dependenciesdevDependenciespeerDependenciesoptionalDependenciesbundledDependenciesengines 脚本配置scriptscon…...
联表查询 索引 事务 JDBC使用 CPU工作原理 线程概念 Thread类的用法
第 1 题(单选题) 题目名称: 已知表T1中有2行数据,T2中有3行数据,执行SQL语句,“select a.* from T1 a,T2 b”后,返回的行数为 题目内容: A .2 B .3 C .5 D .6 第 2 题(单选题…...
网站空间更换/常州网络推广平台
本文将简单介绍RSA在webshell中的使用,旨在帮助小白们快速制作自己的流量混淆工具。关于RSA援引百度百科对RSA的介绍:RSA是1977年由罗纳德李维斯特(Ron Rivest)、阿迪萨莫尔(Adi Shamir)和伦纳德阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省…...
济南能源建设网站/台州网站建设
今天无聊看了一下这个复选框的用法,用它来制作选择题的确是不错的选择。分别在组件面板拖动四个组件, 修改它的标签,让它成为自己适合的答案。还有一些data 的值,和选中状态等。 设置完组件的属性后,开始我们的制作&am…...
做网站cdn加速有什么用/推广优化排名
#include<iostream> #include<Windows.h>//Sleep调用 using namespace std; int main() {std::cout << "\n正在输出记录数据...... ";for( int i0; i < 100; i ) // 打印百分比 {std::cout.width(3);//i的输出为3位宽std::cout << i…...
怎么用织梦模板做网站/如何网络推广新产品
2019独角兽企业重金招聘Python工程师标准>>> wampserver开启php_ldap扩展问题记录 在win7(64位)下使用wampserver,开启php_ldap扩展问题,除了要在php.ini中配置外,还要把php_ldap必须的 libsasl.dll依赖放…...
wordpress复制数据库结构/互联网营销培训
Ubuntu环境下的“批处理”长时间生活在CLI中,“批处理”绝对能简化不少工作。在Windows环境中,建立一个后缀名为.bat的文件,输入需要的指令,保存之后执行即可,十分方便。其实在Ubuntu中也有类似的功能,而且…...
wordpress可以建网站吗/今天热搜榜前十名
以前写过SSG连接的例子现在SSG快没了,替代品SRX原理上因为SRX就是SSG的替代型号,很多地方原理是一样的,所以就不在累述了。这里只说明SRX的配置,作为固定IP方出现在JUNOS Software Release [12.1R7.9]版本下通过测试。st0 { …...