策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算饭的客户.
先定义一个简单的输入表单:
<!DOCTYPE html> <html> <head> <meta charset="utf-"> <style> .form{ width: px; height: px; #margin: px auto; } .form-item-label{ width:px; text-align: right; float: left; } .form-item-input{ float: left; } .form-item{ width: % ; height: px; line-height: px; } </style> </head> <body> <div class='form'> <div class="form-item"> <div class='form-item-label'><span>用户名:</span></div> <div class='form-item-input'><input id='userName' name='用户名' type="text"></div> </div> <div class="form-item" > <div class='form-item-label'><span>密码:</span></div> <div class='form-item-input'><input id='password' name='密码' type="text"></div> </div> <div class="form-item" > <div class='form-item-label'><span>确认密码:</span></div> <div class='form-item-input'><input id='repassword' name='密码确认' type="text"></div> </div> <div class="form-item" > <div class='form-item-label'><span>邮箱:</span></div> <div class='form-item-input'><input id='mail' name='邮箱' type="text" ></div> </div> </div> <br> <button id='submit' >提交</button> <script type='text/javascript' src="../reference/jquery-...min.js"></script> </body> </html>
一般在页面上编辑信息后的提交动作中,都需要对输入的信息进行验证,会看到把很多负责check的代码写在提交函数中或者写在一个独立的check函数中。
比如像下面这样。
$(document).ready(function(){ $('#submit').bind('click', doSubmit); }); function doSubmit(){ var eleUserName = document.getElementById('userName'); if(eleUserName.value === '') { alert('用户名不能为空'); return; } if(eleUserName.length < 6) { alert('用户名长度不能少于6个字符'); return; } if(eleUserName.length > 6) { alert('用户名长度不能多于20个字符'); return; } }
这样的写法功能上肯定能满足要求,但是,会存在几个问题:
1.如果我要在其他页面上使用,那就要将代码进行复制,所谓的复用就变成了复制,代码会存在大量重复。好一点的会把check代码分类整理封装,单还会存在较多的重复复制。
2.如果我要增加一个输入验证,那么就要直接修改提交函数,该函数会显的臃肿,并且是破坏“开闭”原则的。
3.如果修改了提交函数,就要将函数设计的测试全都覆盖一遍,因为,不知道何时就会发生误改或者未知的情况。
改造步骤:
1.将每个验证逻辑看成是一个验证策略并封装成每个验证策略函数,函数参数保持一致,可以接受dom元素,被验证的值,错误消息,定制参数。
2.定义验证器,可将验证策略函数导入,也可以添加。
3.验证器提供验证方法,用于验证时的调用,其内部调用具体的验证策略函数。
4.验证调用。
步骤1.
把每一个if都看成一种校验的业务规则,把每种业务规则作为一个单独的策略函数,将所有的策略函数封装成一个策略对象。
var validationStrategies = { isNoEmpty: function(element, errMsg, value) { if(value === '') { return this.buildInvalidObj(element, errMsg, value ); } }, minLength: function(element, errMsg, value, length) { if(value.length < length){ return this.buildInvalidObj(element, errMsg, value); } }, maxLength: function(element, errMsg, value, length) { if(value.length > length){ return this.buildInvalidObj(element, errMsg, value); } }, isMail: function(element, errMsg, value, length) { var reg = /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/; if(!reg.test(value)){ return this.buildInvalidObj(element, errMsg, value); } } };
所有函数的参数的前3个都保持一致,而且是必须的,表示被验证的DOM元素,错误消息,被验证的值,第4个开始由函数自身的验证规则决定定制的参数,可有多个参数。
“buildInvalidObj”方法只是把前3个参数打成一个错误对象进行返回,只要验证不通过就会返回这个错误对象。
根据依赖倒置原则,高层次的模块不应该依赖于低层次的模块,因此不能让验证的调用方直接使用。
通过验证器的方式进行封装和抽象。
步骤2:
定义验证器,可以将所有验证策略导入其内,也可以单独添加验证策略函数。
//输入验证器 function InputValidators(){ this.validators = []; this.strategies = {}; } //从策略对象导入验证策略函数 //参数: // strategies: 包含各种策略函数的对象 InputValidators.prototype.importStrategies = function(strategies) { for(var strategyName in strategies) { this.addValidationStrategy(strategyName, strategies[strategyName]); } }; //添加验证策略函数 //参数: // name: 策略名称 // strategy: 策略函数 InputValidators.prototype.addValidationStrategy = function(name, strategy){ this.strategies[name] = strategy; };
步骤3:
添加验证方法,接受外部调用。
第一个参数rule,设置成验证规则,比如 "minLength:6",通过下面的代码会生成对具体策略函数的调用,调用会压到缓存中,等待一起调用。
":6"表示策略函数根据自身规则所定制的参数。
//添加验证方法 //参数: // rule: 验证策略字符串 // element: 被验证的dom元素 // errMsg: 验证失败时显示的提示信息 // value: 被验证的值 InputValidators.prototype.addValidator = function(rule, element, errMsg, value) { var that = this; var ruleElements = rule.split(":"); this.validators.push(function() { var strategy = ruleElements.shift(); var params = ruleElements; params.unshift(value); params.unshift(errMsg); params.unshift(element); return that.strategies[strategy].apply(that, params); }); };
通过一个check函数来调用所有的验证。并将错误的结果进行返回。
//开始验证 InputValidators.prototype.check = function() { for(var i = 0, validator; validator = this.validators[i++];){ var result = validator(); if(result) { return result; } } };
步骤4:
在需要验证的地方,先new一个验证器对象。
var validators = new InputValidators();
将包含验证策略函数的对象导入,或者单独添加验证策略函数。
validators.importStrategies(validationStrategies); validators.addValidationStrategy('isEqual', function(element, errMsg, value1, value2) { if(value1 !== value2) { return this.buildInvalidObj(element, errMsg, value1 ); } });
可以看出,不同的验证策略我们可以预先封装进策略对象中,也可以根据实际情况即时添加。
然后通过添加验证方法将需要验证的策略,被验证的dom元素,错误消息,被验证的值添加进验证器中,这样避免了直接调用策略对象,降低了耦合性。
var eleUserName = document.getElementById('userName'); validators.addValidator('isNoEmpty', eleUserName, '用户名不能为空', eleUserName.value); validators.addValidator('minLength:6', eleUserName, '用户名的字符个数必须是6到20个', eleUserName.value); validators.addValidator('maxLength:20', eleUserName, '用户名的字符个数必须是6到20个', eleUserName.value); var elePassword = document.getElementById('password'); validators.addValidator('isNoEmpty', elePassword, '密码不能为空', elePassword.value); validators.addValidator('minLength:6', elePassword, '密码的字符个数必须是6到20个', elePassword.value); validators.addValidator('maxLength:20', elePassword, '密码的字符个数必须是6到20个', elePassword.value); var eleRepassword = document.getElementById('repassword'); validators.addValidator('isNoEmpty', eleRepassword, '确认密码不能为空', eleRepassword.value); validators.addValidator('minLength:6', eleRepassword, '确认密码的字符个数必须是6到20个', eleRepassword.value); validators.addValidator('maxLength:20', eleRepassword, '确认密码的字符个数必须是6到20个', eleRepassword.value); validators.addValidator('isEqual:' + elePassword.value, eleRepassword, '两次密码不一致', eleRepassword.value); var eleMail = document.getElementById('mail'); validators.addValidator('isNoEmpty', eleMail, '邮箱不能为空', eleMail.value); validators.addValidator('isMail', eleMail, '邮箱不是一个有效的格式', eleMail.value);
调用验证器的check执行所有的验证。
var result = validators.check(); if(result){ alert(result.errMsg); result.element.focus(); result.element.select(); return false; }
check返回的是错误对象,我们可以在check后通过该对象统一地对DOM元素进行提示性操作,比如设置焦点,选中内容,或者为输入框外部包上一层红色的样式。
至此,可以看出通过策略模式的改在,输入验证时,我们只需要关心用哪个验证规则,采用什么样的提示性信息即可,不再暴露实现细节,方便调用,方便后续的扩展和组件化。
全部代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> .form{ width: 400px; height: 200px; #margin: 0px auto; } .form-item-label{ width:100px; text-align: right; float: left; } .form-item-input{ float: left; } .form-item{ width: 100% ; height: 50px; line-height: 50px; } </style> </head> <body> <div class='form'> <div class="form-item"> <div class='form-item-label'><span>用户名:</span></div> <div class='form-item-input'><input id='userName' name='用户名' type="text"></div> </div> <div class="form-item" > <div class='form-item-label'><span>密码:</span></div> <div class='form-item-input'><input id='password' name='密码' type="text"></div> </div> <div class="form-item" > <div class='form-item-label'><span>确认密码:</span></div> <div class='form-item-input'><input id='repassword' name='密码确认' type="text"></div> </div> <div class="form-item" > <div class='form-item-label'><span>邮箱:</span></div> <div class='form-item-input'><input id='mail' name='邮箱' type="text" ></div> </div> </div> <br> <button id='submit' >提交</button> <script type='text/javascript' src="../reference/jquery-1.11.3.min.js"></script> <script type='text/javascript'> $(document).ready(function(){ $('#submit').bind('click', doSubmit); }); function doSubmit(){ var validators = new InputValidators(); validators.importStrategies(validationStrategies); validators.addValidationStrategy('isEqual', function(element, errMsg, value1, value2) { if(value1 !== value2) { return this.buildInvalidObj(element, errMsg, value1 ); } }); var eleUserName = document.getElementById('userName'); validators.addValidator('isNoEmpty', eleUserName, '用户名不能为空', eleUserName.value); validators.addValidator('minLength:6', eleUserName, '用户名的字符个数必须是6到20个', eleUserName.value); validators.addValidator('maxLength:20', eleUserName, '用户名的字符个数必须是6到20个', eleUserName.value); var elePassword = document.getElementById('password'); validators.addValidator('isNoEmpty', elePassword, '密码不能为空', elePassword.value); validators.addValidator('minLength:6', elePassword, '密码的字符个数必须是6到20个', elePassword.value); validators.addValidator('maxLength:20', elePassword, '密码的字符个数必须是6到20个', elePassword.value); var eleRepassword = document.getElementById('repassword'); validators.addValidator('isNoEmpty', eleRepassword, '确认密码不能为空', eleRepassword.value); validators.addValidator('minLength:6', eleRepassword, '确认密码的字符个数必须是6到20个', eleRepassword.value); validators.addValidator('maxLength:20', eleRepassword, '确认密码的字符个数必须是6到20个', eleRepassword.value); validators.addValidator('isEqual:' + elePassword.value, eleRepassword, '两次密码不一致', eleRepassword.value); var eleMail = document.getElementById('mail'); validators.addValidator('isNoEmpty', eleMail, '邮箱不能为空', eleMail.value); validators.addValidator('isMail', eleMail, '邮箱不是一个有效的格式', eleMail.value); var result = validators.check(); if(result){ alert(result.errMsg); result.element.focus(); result.element.select(); return false; } alert('验证通过'); } //输入验证器 function InputValidators(){ this.validators = []; this.strategies = {}; //this.from(validationStrategies); } //添加验证方法 //参数: // rule: 验证策略字符串 // element: 被验证的dom元素 // errMsg: 验证失败时显示的提示信息 // value: 被验证的值 InputValidators.prototype.addValidator = function(rule, element, errMsg, value) { var that = this; var ruleElements = rule.split(":"); this.validators.push(function() { var strategy = ruleElements.shift(); var params = ruleElements; params.unshift(value); params.unshift(errMsg); params.unshift(element); return that.strategies[strategy].apply(that, params); }); }; //添加验证策略函数 //参数: // name: 策略名称 // strategy: 策略函数 InputValidators.prototype.addValidationStrategy = function(name, strategy){ this.strategies[name] = strategy; }; //从策略对象导入验证策略函数 //参数: // strategies: 包含各种策略函数的对象 InputValidators.prototype.importStrategies = function(strategies) { for(var strategyName in strategies) { this.addValidationStrategy(strategyName, strategies[strategyName]); } }; //验证失败时,将相关的错误信息打包返回 //参数: // element: dom元素 // errMsg: 验证失败时的提示消息 // value: 被验证的值 InputValidators.prototype.buildInvalidObj = function(element, errMsg, value){ return { 'value': value, 'element': element, 'errMsg': errMsg }; }; //开始验证 InputValidators.prototype.check = function() { for(var i = 0, validator; validator = this.validators[i++];){ var result = validator(); if(result) { return result; } } }; //验证策略对象,包含默认的验证策略函数 var validationStrategies = { isNoEmpty: function(element, errMsg, value) { if(value === '') { return this.buildInvalidObj(element, errMsg, value ); } }, minLength: function(element, errMsg, value, length) { if(value.length < length){ return this.buildInvalidObj(element, errMsg, value); } }, maxLength: function(element, errMsg, value, length) { if(value.length > length){ return this.buildInvalidObj(element, errMsg, value); } }, isMail: function(element, errMsg, value, length) { var reg = /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/; if(!reg.test(value)){ return this.buildInvalidObj(element, errMsg, value); } } }; </script> </body> </html>
以上所述是小编给大家介绍的javascript设计模式--策略模式之输入验证的全部内容,希望大家喜欢。

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

Dreamweaver Mac版
视觉化网页开发工具

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。