The strategy pattern defines a family of algorithms and encapsulates them separately so that they can be replaced with each other. This pattern makes the algorithm changes independent of the customers who use the calculation.
First define a simple input form:
<!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>
Generally, in the submission action after editing information on the page, the input information needs to be verified. You will see that a lot of code responsible for checking is written in the submission function or in an independent check function.
For example, like below.
$(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; } }
This writing method can definitely meet the functional requirements, but there will be several problems:
1. If I want to use it on other pages, I have to copy the code. The so-called reuse becomes copying, and there will be a lot of duplication of the code. Better ones will classify and package the check code, but there will be more duplication.
2. If I want to add an input verification, then I have to directly modify the submission function. This function will be bloated and destroy the "opening and closing" principle.
3. If you modify the submission function, you must cover all the tests of the function design, because you don’t know when mistaken changes or unknown situations will occur.
Transformation steps:
1. Treat each verification logic as a verification strategy and encapsulate each verification strategy function. The function parameters should be consistent and can accept DOM elements, verified values, error messages, and customized parameters.
2. Define the validator, you can import the validation strategy function or add it.
3. The validator provides a verification method for calling during verification, and internally calls a specific verification strategy function.
4. Verify the call.
Step 1.
Consider each if as a verification business rule, treat each business rule as a separate strategy function, and encapsulate all strategy functions into a strategy object.
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); } } };
The first three parameters of all functions are consistent and required, indicating the verified DOM element, error message, and verified value. The fourth one starts with the function’s own verification rules to determine the customized parameters. Can have multiple parameters.
The "buildInvalidObj" method just converts the first three parameters into an error object and returns it. This error object will be returned as long as the verification fails.
According to the dependency inversion principle, high-level modules should not depend on low-level modules, so they cannot be used directly by the caller of verification.
Encapsulation and abstraction through validators.
Step 2:
Define the validator, you can import all the verification strategies into it, or you can add the verification strategy functions separately.
//输入验证器 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; };
Step 3:
Add verification method to accept external calls.The first parameter rule is set to a verification rule, such as "minLength:6". The following code will generate a call to the specific strategy function. The call will be pushed into the cache and wait to be called together.
":6" indicates the parameters customized by the strategy function according to its own rules.
//添加验证方法 //参数: // 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); }); };
//开始验证 InputValidators.prototype.check = function() { for(var i = 0, validator; validator = this.validators[i++];){ var result = validator(); if(result) { return result; } } };
Step 4:
Where verification is required, first create a new validator object.
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);
check returns an error object. We can use this object to uniformly perform prompt operations on DOM elements after check, such as setting focus, selecting content, or wrapping a layer of red style on the outside of the input box.
var result = validators.check(); if(result){ alert(result.errMsg); result.element.focus(); result.element.select(); return false; }
All codes:
The above is the entire content of the javascript design pattern introduced by the editor - strategy pattern input verification. I hope you like it.