戦略パターンはアルゴリズムのファミリーを定義し、それらを個別にカプセル化して、計算を使用する顧客に関係なくアルゴリズムを変更できるようにします。
まず簡単な入力フォームを定義します:
<!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>
一般に、ページ上の情報を編集した後の送信アクションでは、入力された情報を検証する必要があります。送信関数または独立したチェック関数に、チェックを担当する多くのコードが記述されていることがわかります。
例えば以下のような感じです。
$(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. 他のページで使用したい場合は、コードをコピーする必要があり、いわゆる再利用はコードの重複が多くなります。より良いものはチェックコードを分類してパッケージ化しますが、重複が多くなります。
2. 入力認証を追加したい場合は、送信機能を直接変更する必要があり、この機能は肥大化し、「開閉」の原則が崩れてしまいます。
3. 送信関数を変更する場合は、いつ誤った変更や未知の状況が発生するかわからないため、関数設計のすべてのテストをカバーする必要があります。
変換手順:
1. 各検証ロジックを検証戦略として扱い、各検証戦略関数をカプセル化します。関数パラメーターは一貫性があり、DOM 要素、検証された値、エラー メッセージ、カスタマイズされたパラメーターを受け入れることができます。
2. バリデーターを定義します。検証戦略関数をインポートまたは追加できます。
3. バリデーターは検証中に呼び出すための検証メソッドを提供し、内部的に特定の検証戦略関数を呼び出します。
4. 通話を確認します。
ステップ 1.
各 if を検証ビジネス ルールとして考慮し、各ビジネス ルールを個別の戦略関数として扱い、すべての戦略関数を 1 つの戦略オブジェクトにカプセル化します。
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:
外部呼び出しを受け入れるための検証方法を追加します。最初のパラメーター ルールは、「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); }); };
//开始验证 InputValidators.prototype.check = function() { for(var i = 0, validator; validator = this.validators[i++];){ var result = validator(); if(result) { return result; } } };
ステップ 4:
検証が必要な場合は、まず新しいバリデーター オブジェクトを作成します。
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 はエラー オブジェクトを返します。このオブジェクトを使用すると、チェック後に DOM 要素に対してプロンプト操作 (フォーカスの設定、コンテンツの選択、入力ボックスの外側の赤いスタイルのレイヤーのラップなど) を均一に実行できます。
var result = validators.check(); if(result){ alert(result.errMsg); result.element.focus(); result.element.select(); return false; }
すべてのコード:
以上が編集者が紹介するJavaScriptデザインパターン - 戦略パターン入力検証の全内容です。気に入っていただければ幸いです。