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

策略模式,一种广泛应用于各种情况的设计模式(设计模式与开发实践 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)

文章目录 策略模式实现思想实战 - 表单 策略模式 定义&#xff1a;定义一系列算法&#xff0c;把它们一个个封装起来&#xff0c;并且可以互相替换 例如&#xff0c;我们要计算年终奖&#xff0c;年终奖根据绩效 A、B、C 来计算最终数值 实现 最初我们很容易想到用 分支 if…...

90. 子集 II

给你一个整数数组 nums &#xff0c;其中可能包含重复元素&#xff0c;请你返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。返回的解集中&#xff0c;子集可以按 任意顺序 排列。 示例 1&#xff1a; 输入&#xff1a;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)中文名称为探索性数据分析&#xff0c;是为了在特征工程或模型开发之前对数据有个基本的了解。数据类型通常分为两类&#xff1a;连续类型和离散类型&#xff0c;特征类型不同&#xff0c;我们探索的内容也不同。 1. 特征类型 1.1 连续型特征 …...

Python中的多媒体处理库有哪些?

在Python中&#xff0c;有几个常用的多媒体处理库&#xff0c;包括&#xff1a; Pillow - 一个强大的图像处理库&#xff0c;可以进行图像的读取、保存、剪裁、调整大小、滤镜处理等操作。 OpenCV - 一个用于图像和视频处理的开源计算机视觉库&#xff0c;提供了许多图像处理和…...

LeetCode【28. 找出字符串中第一个匹配项的下标】

不要用珍宝装饰自己&#xff0c;而要用健康武装身体 给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。如果 needle 不是 haystack 的一部分&#xff0c;则返回 -1 。 …...

产业互联网开始从简单的概念,逐渐成为可以落地的存在

当流量不再是红利&#xff0c;几乎所有的消费互联网模式开始失效。这一现象&#xff0c;并不仅仅只是体现在流量获取成本的不断增加上&#xff0c;同样还体现在流量激活的难度不断增加上。事实证明&#xff0c;以产业链末端为主要驱动力的发展模式&#xff0c;正在走入到死胡同…...

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正向扩散数据准备与处理采样训练过程推理过程&#xff08;从模型中采样&#xff09; 本文基于Hugging Face&#x…...

华为CD32键盘使用教程

华为CD32键盘使用教程 用爱发电写的教程&#xff01; 最后更新时间&#xff1a;2023.9.12 型号&#xff1a;华为有线键盘CD32 基本使用 此键盘在不安装驱动的情况下可以直接使用&#xff0c;但是不安装驱动指纹识别是无法使用的&#xff01;并且NFC功能只支持华为的部分电脑…...

第三节:在WORD为应用主窗口下关闭EXCEL的操作(2)

【分享成果&#xff0c;随喜正能量】凡事好坏&#xff0c;多半自作自受&#xff0c;既不是神为我们安排&#xff0c;也不是天意偏私袒护。业力之前&#xff0c;机会均等&#xff0c;毫无特殊例外&#xff1b;好坏与否&#xff0c;端看自己是否能应机把握&#xff0c;随缘得度。…...

Layui + Flask | 弹出层(组件篇)(04)

提示:点击阅读原文体验更佳 https://layui.dev/docs/2.8/layer/ 弹出层组件 layer 是 Layui 最古老的组件,也是使用覆盖面最广泛的代表性组件。在实现网页弹出层的首选交互方案,使用的非常频繁。 打开弹层 layer.open(options); 参数 options : 基础属性配置项。打开弹层的核…...

Electron和vue3集成(推荐仅用于开发)

本篇我们仅实现Electron和vue3通过先运行起vue3项目&#xff0c;再将vue3的url地址交由Electron打开的方案&#xff0c;仅由Electron在vue3项目上套一层壳来达到脱离本机浏览器运行目的 1、参考快速上手 | Vue.js搭建起vue3初始项目 npm install -g vue npm install -g vue/c…...

Vue.js和TypeScript:如何完美结合

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

034:vue项目利用qrcodejs2生成二维码示例

第034个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…...

执行 git remote add github git@github.com:xxxx/testGit.git时,git内部做了啥?

git remote add 往 .git/config 中写入了一个叫 [remote "origin"] 配置 url → 表示该远程名称对应的远程仓库地址fetch 参数分为两部分&#xff0c;以冒号 : 进行分割冒号左边 ☞ 本地仓库文件夹冒号右边 ☞ 远程仓库在本地的副本文件夹 ☞ 往里面添加数据的意思 可…...

Makefile基础

迷途小书童 读完需要 4分钟 速读仅需 2 分钟 1 引言 下面这个 C 语言的代码非常简单 #include <stdio.h>int main() {printf("Hello World!.\n");return 0; } 在 Linux 下面&#xff0c;我们使用下面的命令编译就可以 gcc hello.c -o hello 但是随着项目的变大…...

【PickerView案例08-国旗搭建界面加载数据 Objective-C预言】

一、来看我们第三个案例 1.来看我们第三个关于PickerView的一个案例, 首先呢,我要问大家一下, 咱们这个是几组数据呢, 这是一个pickerView,只不过,它显示的是什么,一个界面, 前面两个案例,都是文字 这个案例,开始有图片了, 总结一下这三个案例: 1)第一个案例…...

2023-09-15力扣每日一题

链接&#xff1a; [LCP 50. 宝石补给](https://leetcode.cn/problems/queens-that-can-attack-the-king/) 题意 略 解&#xff1a; 简单题 模拟 实际代码&#xff1a; int giveGem(vector<int>& gem, vector<vector<int>>& operations) {for(…...

系列七、Nginx负载均衡配置

一、目标 浏览器中访问http://{IP地址}:9002/edu/index.html&#xff0c;浏览器交替打印清华大学8080、清华大学8081. 二、步骤 2.1、在tomcat8080、tomcat8081的webapps中分别创建edu文件夹 2.2、将index.html分别上传至edu文件夹 注意事项&#xff1a;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 开源社区负责人&#xff0c; Apache Flink PMC Member & Committer 徐榜江&#xff08;雪尽&#xff09;&#xff0c;在 Streaming Lakehouse Meetup 的分享。内容主要分为四个部分&#xff1a; Flink CDC 核心技术解析数…...

redis的基础底层篇 zset的详解

一 zset的作用以及结构 1.1 zset作用 redis的zset是一个有序的集合&#xff0c;和普通集合set非常相似&#xff0c;是一个没有重复元素的字符串集合。常用作排行榜等功能&#xff0c;以用户 id 为 value&#xff0c;关注时间或者分数作为 score 进行排序。 1.2 zset的底层结…...

数据分享|R语言逻辑回归、线性判别分析LDA、GAM、MARS、KNN、QDA、决策树、随机森林、SVM分类葡萄酒交叉验证ROC...

全文链接:http://tecdat.cn/?p27384 在本文中&#xff0c;数据包含有关葡萄牙“Vinho Verde”葡萄酒的信息&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 介绍 该数据集&#xff08;查看文末了解数据获取方式&#xff09;有1599个观测值和12个变量&#xf…...

Open3D(C++) 点云旋转的轴角表示法和罗德里格斯公式

目录 一、算法原理1、轴角表示法2、罗德里格斯公式二、代码实现三、结果展示四、相关链接一、算法原理 1、轴角表示法 假设刚体坐标系为B(Oxyz)绕单位向量 ω ⃗ \vec{ω}...

CPU的三级缓存

CPU缓存&#xff08;Cache Memory&#xff09;是位于CPU与内存之间的临时存储器&#xff0c;它的容量比内存小的多但是交换速度却比内存要快得多。高速缓存的出现主要是为了解决CPU运算速度与内存读写速度不匹配的矛盾&#xff0c;因为CPU运算速度要比内存读写速度快很多&#…...

pgzrun 拼图游戏制作过程详解(6,7)

6. 检查拼图完成 初始化标记成功的变量Is_Win Is_WinFalse 当鼠标点击小拼图时&#xff0c;判断所有小拼图是否都在正确的位置&#xff0c;并更新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 通常返回一个集合作为结果&#xff0c;集合包含很多有用的、功能强大的方法。 你可以很方便的对集合进行过滤、修改等操作。 本次教程就一起来看一看集合的常用方法及功能。 你可以使用助手函数 collect 将数组转化为集合。 $data collect([1, 2, 3]); 1…...

[npm]package.json文件

[npm]package.json文件 生成 package.jsonpackage.json 必须属性nameversion 描述信息descriptionkeywordsauthorcontributorshomepagerepositorybugs 依赖配置dependenciesdevDependenciespeerDependenciesoptionalDependenciesbundledDependenciesengines 脚本配置scriptscon…...

联表查询 索引 事务 JDBC使用 CPU工作原理 线程概念 Thread类的用法

第 1 题&#xff08;单选题&#xff09; 题目名称&#xff1a; 已知表T1中有2行数据&#xff0c;T2中有3行数据&#xff0c;执行SQL语句,“select a.* from T1 a,T2 b”后&#xff0c;返回的行数为 题目内容&#xff1a; A .2 B .3 C .5 D .6 第 2 题&#xff08;单选题…...

网站空间更换/常州网络推广平台

本文将简单介绍RSA在webshell中的使用&#xff0c;旨在帮助小白们快速制作自己的流量混淆工具。关于RSA援引百度百科对RSA的介绍&#xff1a;RSA是1977年由罗纳德李维斯特(Ron Rivest)、阿迪萨莫尔(Adi Shamir)和伦纳德阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省…...

济南能源建设网站/台州网站建设

今天无聊看了一下这个复选框的用法&#xff0c;用它来制作选择题的确是不错的选择。分别在组件面板拖动四个组件&#xff0c; 修改它的标签&#xff0c;让它成为自己适合的答案。还有一些data 的值&#xff0c;和选中状态等。 设置完组件的属性后&#xff0c;开始我们的制作&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&#xff08;64位&#xff09;下使用wampserver&#xff0c;开启php_ldap扩展问题&#xff0c;除了要在php.ini中配置外&#xff0c;还要把php_ldap必须的 libsasl.dll依赖放…...

wordpress复制数据库结构/互联网营销培训

Ubuntu环境下的“批处理”长时间生活在CLI中&#xff0c;“批处理”绝对能简化不少工作。在Windows环境中&#xff0c;建立一个后缀名为.bat的文件&#xff0c;输入需要的指令&#xff0c;保存之后执行即可&#xff0c;十分方便。其实在Ubuntu中也有类似的功能&#xff0c;而且…...

wordpress可以建网站吗/今天热搜榜前十名

以前写过SSG连接的例子现在SSG快没了&#xff0c;替代品SRX原理上因为SRX就是SSG的替代型号&#xff0c;很多地方原理是一样的&#xff0c;所以就不在累述了。这里只说明SRX的配置&#xff0c;作为固定IP方出现在JUNOS Software Release [12.1R7.9]版本下通过测试。st0 { …...