俗话说,凡事讲策略。讲策略的时候,我们往往会考虑每种情况的成本。策略同样可体现在我们的代码之中,合理利用策略模式重构逻辑复杂的代码,会使项目工程更易维护和扩展。
这几天朋友圈被“新生代农民工”刷屏了,看到有这样一张截图:
代码里写了约 30 个if else
逻辑,从程序语义以及程序效率理论上是会有一定的影响,最主要的是可能会被其他“新生代农民工”嘲笑
一位经验老道的民工则会用一手switch case
或策略模式来重构代码,那么什么是策略模式呐?
策略:为实现一定的战略任务,根据形势发展而制定的行动方针和斗争方式。策略模式:一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,以使算法的对象能够相互替换。在常见的前端游戏奖励激励交互中,常常会涉及到不同分数会展示不同的动效,这其实就是一种条件策略。
优点:
缺点:
策略模式指的是定义了一系列算法,把它们每个都封装起来。将不变的部分和变化的部分隔离开来是设计模式中的一个重要思想,策略模式则是将算法和使用算法两部分的实现拆开,降低耦合度。基于策略模式的程序至少有两部分组成:策略类和环境类(Context
)。策略类封装了具体的算法,并负责具体的计算过程,可以理解为“执行者”。环境类(Context
)接受客户的请求,然后将请求委托给一个策略类,可以理解为“调度者”。
在 Web 项目中,常见的表单有注册、登陆、修改用户信息等涉及到表单的功能,与此同时我们会在表单提交的时候,做一些例的前端输入框值的条件校验工作。由于输入框中用户的输入是任意的,校验的规则相对比较复杂,如果不使用设计模式,我们的代码中可能就会写出较多的if else
判断逻辑,从可阅读性和可维护性来说,确实不是很好。接下来我们将从前端 Web 项目中常见的表单验证功能,逐步认识策略设计模式。
在很久很久以前,我的表单验证可能是这么写的:
var username = $('#nuserame').val();
var password = $('#password').val();
if (!username) {
alert('用户名不能为空');
} else if (username.length < 5) {
alert('用户名长度需要大于等于5');
} else if (username.length < 13) {
alert('用户名长度需要小于13');
} else if (!(/[a-z]+/i.test(username))) {
alert('用户名只能包含英文大小写字符')
} else {
regeister(username);
}
// password的验证同上
写法似乎有些不忍直视,不过能用!
换个思路,结合策略模式的思想,实现一个专用于值校验的Validator
类,Validator
是一个调度者,也就是策略模式中的环境类。然后我们在验证目标字段值targetValue
的时候其用法大致如下:
Validator.addRules(targetValue, ['isNonEmpty', 'minLength:5', 'maxLength:12']).valid();
校验器会返回判断结果result
字段,以及语义话的提示msg
字段:
return {
result: false,
msg: '不能为空'
}
根据上述需求,Validator 的实现如下:
const formatResult = (isPass: boolean = false, errMsg: string = "") => {
return {
result: isPass,
msg: errMsg,
};
};
const ValidStrategies = {
isNonEmpty: function (val: string = "") {
if (!val) return formatResult(false, "内容不能为空");
},
minLength: function (val: string = "", length: string | number = 0) {
console.log(val, length);
if (typeof length === "string") length = parseInt(length);
if (val.length < length)
return formatResult(false, `内容长度不能小于 ${length}`);
},
maxLength: function (val: string = "", length: string | number = 0) {
if (typeof length === "string") length = parseInt(length);
if (val.length > length)
return formatResult(false, `内容长度不能大于 ${length}`);
},
default: function () {
return formatResult(true);
},
};
/**
* 验证器
* 策略模式 —— 环境类,负责调度算法
*/
class Validator {
// 存储规则
private _ruleExecuters: Array<any>;
constructor() {
this._ruleExecuters = [];
}
/**
* addRules
* 添加校验规则
*/
public addRules(value: string = "", rules: Array<string>) {
this._ruleExecuters = [];
rules.forEach((rule) => {
const args = rule.split(":");
const functionName = args.shift() || "default";
// 忽略下这里的断言类型
const ruleFunc = ValidStrategies[
functionName as "isNonEmpty" | "minLength" | "maxLength" | "default"
].bind(this, value);
this._ruleExecuters.push({
func: ruleFunc,
args,
});
});
return this;
}
/**
* valid
*/
public valid() {
for (let i = 0; i < this._ruleExecuters.length; i++) {
const res = this._ruleExecuters[i].func.apply(
this,
this._ruleExecuters[i].args
);
if (res && !res.result) {
return res;
}
}
return formatResult(true);
}
}
export default new Validator();
const res = Validator.addRules("123", [
"isNonEmpty",
"minLength:5",
"maxLength:12",
]).valid();
console.log("res:", res);
这样在验证表单值的时候,我们就可以直接调用 Validator 验证值的合法性。与此同时,还可以通过扩展策略类(对象)ValidStrategies
中的验证算法来扩展校验器的能力。
策略模式节省逻辑判断的特性让我联想到了之前看过的一个概念“表驱动法”,或者叫“查表法”,这里引用下百度百科的解释:
表驱动方法出于特定的目的来使用表,程序员们经常谈到“表驱动”方法,但是课本中却从未提到过什么是"表驱动"方法。表驱动方法是一种使你可以在表中查找信息,而不必用很多的逻辑语句(
if
或Case
)来把它们找出来的方法。事实上,任何信息都可以通过表来挑选。在简单的情况下,逻辑语句往往更简单而且更直接。但随着逻辑链的复杂,表就变得越来越富有吸引力了。
举个 ,假设我们想要获取当前是星期几,代码可能是这样的:
function getDay() {
const day = (new Date()).getDay();
switch (day) {
case 0:
return '星期日';
case 1:
return '星期一';
// ...
case 6:
return '星期六';
default:
return '';
}
}
```Javascript
如果是初次编程的同学还可能会有`if else`条件语句来判断返回值,代码就会显得比较冗余。借助表驱动发法的思想,这里我们是可以有优化空间的,表驱动发法的写法如下:
```js
const days = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
function getDay2() {
return days[(new Date()).getDay()];
}
当然上述只是一个非常简单的 ,大家在编码过程中只需要主要点,如有涉及类似场景,请用这种方式去编码,体验更愉悦!
策略设计模式让各种算法的代码、内部数据和依赖关系与其他代码隔离开来。不同客户端可通过一个简单接口执行算法,并能在运行时进行切换。当然设计实现功能的时候,如果需要使用策略设计模式,也更需要我们的工程师有一个功能全局把控的能力,以此也能凸显“新生代”的不同!
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/nVlZ9V744DQUNiWBP0m8_Q
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。