- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
策略模式主要解决在有多种情况下,使用 if...else 所带来的 复杂和难以维护 .
它的优点是算法可以自由切换,同时可以避免多重 if...else 判断,且具有良好的扩展性.
我们有一个根据不同的类型返回不同价格的一个方法 。
function getPrice (type) {
if (type === 1) {
// code 或许每个分支要处理很多逻辑
}
if (type === 2) {
// code
}
if (type === 3) {
// code
}
if (type === 4) {
// code
}
if (type === 5) {
// code
}
if (type === 6) {
// code
}
if (type === 7) {
// code
}
}
从 代码上看确实没有什么问题,但是如果需要增加一种新的类型,我们就会一个if判断,导致这个方法可能会过于庞大,后期不太好维护.
其次代码每次都是从上往下走,可能存在前面某个判断出现问题(如某个 && 的判断变量null 之类),导致后面的代码没有走,所以这种影响还是挺大的.
用了这么多 if-else ,我们的目的是什么?是不是就是为了把 传进来的参数的值-对应的处理函数 ,这个映射关系给明确下来?在 JS 中我们可以通过对象映射的形式来做,如下代码 。
/*
1、把 if else 的代码快优化为一个一个的映射
2、把if else 里面的逻辑抽离成一个独立的函数,这样方便其他模块或者分支使用
*/
function getPrice (type) {
const actionMap = {
'1': action1,
'2': action2,
'3': action3,
'4': action4,
'5': action5,
'6': action6,
'7': action7,
}
const params = {}
return actionMap[type](params)
}
这种代码结构变得易读、易维护.
这就是最简单的策略模式 。
如果不把逻辑封装起来,那么我们在判断的时候会写很多的if else,如写一个很简单的表单的校验 。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta content="black" name="apple-mobile-web-app-status-bar-style">
<meta content="telephone=no,email=no" name="format-detection">
<meta name="App-Config" content="fullscreen=yes,useHistoryState=yes,transition=yes">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<link href="css/style.css" rel="stylesheet">
</head>
<body>
<div>
<form action="" id="form">
姓名:<input type="text" id="username"><br>
密码:<input type="password" id="password1"><br>
确认密码:<input type="password" id="password2"><br>
手机号:<input type="text" id="phone"><br>
<input type="submit" value="提交">
</form>
</div>
<script>
function getValue (id) {
return document.getElementById(id).value;
}
var formData = document.getElementById('form')
formData.onsubmit = function () {
var name = getValue('username');
var pwd1 = getValue('password1');
var pwd2 = getValue('password2');
var tel = getValue('phone');
if (name.replace(/(^\s*)|(\s*$)/g, "") === "") {
alert('用户名不能为空')
return false
}
if (pwd1.replace(/(^\s*)|(\s*$)/g, "") === "") {
alert('密码不能为空')
return false
}
if (pwd2.replace(/(^\s*)|(\s*$)/g, "") === "") {
alert('确认密码不能为空')
return false
}
if (pwd2 !== pwd1) {
alert('确认密码与原密码不相同!')
return false
}
if (tel.replace(/(^\s*)|(\s*$)/g, "") === "") {
alert('手机号码不能为空')
return false
}
if (!/^1[3,4,5,7,8,9][0-9]\d{8}$/.test(tel)) {
alert('手机号码格式不正确')
return false
}
alert('注册成功')
}
</script>
</body>
</html>
只是4个字段,我们用了 6个if判断来做相关的逻辑校验.
仔细观察发现很多校验的逻辑是一致的,所以我们可以把他封装起来,用策略模式修改成如下 。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta content="black" name="apple-mobile-web-app-status-bar-style">
<meta content="telephone=no,email=no" name="format-detection">
<meta name="App-Config" content="fullscreen=yes,useHistoryState=yes,transition=yes">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<link href="css/style.css" rel="stylesheet">
</head>
<body>
<div>
<form action="" id="form">
姓名:<input type="text" id="username"><br>
密码:<input type="password" id="password1"><br>
确认密码:<input type="password" id="password2"><br>
手机号:<input type="text" id="phone"><br>
<input type="submit" value="提交">
</form>
</div>
<script>
let formData = document.getElementById('form')
function getValue(id) {
return document.getElementById(id).value;
}
function Validate() { }
Validate.prototype.rules = {
// 是否手机号
isMobile: function (str) {
let rule = /^1[3,4,5,7,8,9][0-9]\d{8}$/;
return rule.test(str);
},
// 是否必填
isRequired: function (str) {
// 除去首尾空格
let value = str.replace(/(^\s*)|(\s*$)/g, "");
return value !== "";
},
// 最小长度
minLength: function (str, length) {
let strLength = str.length;
return strLength >= length;
},
// 是否相等
isEqual: function (...args) {
let equal = args.every(function (value) {
return value === args[0];
})
return equal;
}
}
Validate.prototype.test = function (rules) {
let _this = this;
let valid; // 保存校验结果
for (let key in rules) { // 遍历校验规则对象
for (let i = 0; i < rules[key].length; i++) { // 遍历每一个字段的校验规则
let ruleName = rules[key][i].rule; // 获取每一个校验规则的规则名
let value = rules[key][i].value; // 获取每一个校验规则的校验值
if (!Array.isArray(value)) { // 统一校验值为数组类型
value = new Array(value)
}
let result = _this.rules[ruleName].apply(this, value); // 调用校验规则方法进行校验
if (!result) { // 如果校验不通过,就获取校验结果信息,并立即跳出循环不再执行,节约消耗
valid = {
errValue: key,
errMsg: rules[key][i].message
}
break;
}
}
if (valid) { // 如果有了校验结果,代表存在不通过的字段,则立即停止循环,节约消耗
break;
}
}
return valid; // 把校验结果反悔出去
}
formData.onsubmit = function () {
event.preventDefault()
let validator = new Validate();
let result = validator.test({
'username': [{ rule: 'isRequired', value: this.username.value, message: '用户名不能为空!' }],
'password1': [
{ rule: 'isRequired', value: this.password1.value, message: '密码不能为空!' },
{ rule: 'minLength', value: [this.password1.value, 6], message: '密码长度不能小于6个字符!' }
],
'password2': [
{ rule: 'isRequired', value: this.password2.value, message: '确认密码不能为空!' },
{ rule: 'minLength', value: [this.password2.value, 6], message: '确认密码长度不能小于6个字符!' },
{ rule: 'isEqual', value: [this.password2.value, this.password1.value], message: '确认密码与原密码不相同!' }
],
'isMobile': [
{ rule: 'isRequired', value: this.phone.value, message: '手机号不能为空!' },
{ rule: 'isMobile', value: this.phone.value, message: '手机号格式不正确!' }
]
})
if (result) {
console.log(result);
} else {
console.log('校验通过');
}
}
</script>
</body>
</html>
下次我们增加其他的字段也只是增加规则而已,而不会去修改判断的业务逻辑.
策略模式可看作为 if/else 判断的另一种表现形式,在达到相同目的的同时,极大的减少了代码量以及代码维护成本 。
如果您觉得阅读本文对您有帮助,请点一下 推荐 按钮,您的 推荐 将是我最大的写作动力,欢迎各位转载!
最后此篇关于结构型:策略模式的文章就讲到这里了,如果你想了解更多关于结构型:策略模式的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我目前正在尝试基于哈希表构建字典。逻辑是:有一个名为 HashTable 的结构,其中包含以下内容: HashFunc HashFunc; PrintFunc PrintEntry; CompareF
如果我有一个指向结构/对象的指针,并且该结构/对象包含另外两个指向其他对象的指针,并且我想删除“包含这两个指针的对象而不破坏它所持有的指针”——我该怎么做这样做吗? 指向对象 A 的指针(包含指向对象
像这样的代码 package main import "fmt" type Hello struct { ID int Raw string } type World []*Hell
我有一个采用以下格式的 CSV: Module, Topic, Sub-topic 它需要能够导入到具有以下格式的 MySQL 数据库中: CREATE TABLE `modules` ( `id
通常我使用类似的东西 copy((uint8_t*)&POD, (uint8_t*)(&POD + 1 ), back_inserter(rawData)); copy((uint8_t*)&PODV
错误 : 联合只能在具有兼容列类型的表上执行。 结构(层:字符串,skyward_number:字符串,skyward_points:字符串)<> 结构(skyward_number:字符串,层:字符
我有一个指向结构的指针数组,我正在尝试使用它们进行 while 循环。我对如何准确初始化它并不完全有信心,但我一直这样做: Entry *newEntry = malloc(sizeof(Entry)
我正在学习 C,我的问题可能很愚蠢,但我很困惑。在这样的函数中: int afunction(somevariables) { if (someconditions)
我现在正在做一项编程作业,我并没有真正完全掌握链接,因为我们还没有涉及它。但是我觉得我需要它来做我想做的事情,因为数组还不够 我创建了一个结构,如下 struct node { float coef;
给定以下代码片段: #include #include #define MAX_SIZE 15 typedef struct{ int touchdowns; int intercepti
struct contact list[3]; int checknullarray() { for(int x=0;x<10;x++) { if(strlen(con
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Empty “for” loop in Facebook ajax what does AJAX call
我刚刚在反射器中浏览了一个文件,并在结构构造函数中看到了这个: this = new Binder.SyntaxNodeOrToken(); 我以前从未见过该术语。有人能解释一下这个赋值在 C# 中的
我经常使用字符串常量,例如: DICT_KEY1 = 'DICT_KEY1' DICT_KEY2 = 'DICT_KEY2' ... 很多时候我不介意实际的文字是什么,只要它们是独一无二的并且对人类读
我是 C 的新手,我不明白为什么下面的代码不起作用: typedef struct{ uint8_t a; uint8_t* b; } test_struct; test_struct
您能否制作一个行为类似于内置类之一的结构,您可以在其中直接分配值而无需调用属性? 前任: RoundedDouble count; count = 5; 而不是使用 RoundedDouble cou
这是我的代码: #include typedef struct { const char *description; float value; int age; } swag
在创建嵌套列表时,我认为 R 具有对列表元素有用的命名结构。我有一个列表列表,并希望应用包含在任何列表中的每个向量的函数。 lapply这样做但随后剥离了列表的命名结构。我该怎么办 lapply嵌套列
我正在做一个用于学习目的的个人组织者,我从来没有使用过 XML,所以我不确定我的解决方案是否是最好的。这是我附带的 XML 文件的基本结构:
我是新来的 nosql概念,所以当我开始学习时 PouchDB ,我找到了这个转换表。我的困惑是,如何PouchDB如果可以说我有多个表,是否意味着我需要创建多个数据库?因为根据我在 pouchdb
我是一名优秀的程序员,十分优秀!