JavaScript戦略モデル
11268 ワード
戦略パターンの定義:一連のアルゴリズムを定義し、それらの意味をカプセル化し、相互に置き換えることができる.
ポリシーモードでボーナスを計算します.
ボーナスの支給シーン:パフォーマンスがSの人の年末賞は4倍の給料で、成績はAの年末賞は3倍の給料で、成績はBの年末賞は2倍の給料で、それでは私達のプログラミングのコードです.
最初のコードの実装に多くのレベルがあると、 この関数は弾力性に欠けています.Cを一つ追加すると、Sの係数を変更すると、関数の内部に入って実現しなければなりません.オープン・クローズの原則に違反します. アルゴリズムの多重性が悪く、他のところで重複した論理を行うと、コピー貼り付けしかできず、直接コードの多重化ができない. 上のコードには大きな問題がありますので、コードを再構成することにしました.
組合せ関数を使ってコードの再構成を行うと、私たちが最も容易に考えられる方法は、組合せ関数によってコードの再構成を行うことであり、様々なアルゴリズムを小さな関数にパッケージ化して、これらの小さな関数に良い名前が付けられています.どのアルゴリズムが使われているかを一目で知ることができます.上の使用シーンですか?コードの最適化を行います.
戦略モード再構成コードを使用して、戦略モードを使ってコードを再構成できると考えています.戦略モードの意味は、一連のアルゴリズムを定義し、これらのアルゴリズムをパッケージ化して、不変の部分と変化の部分を分割することが、各設計モードの主要問題であり、戦略モードも例外ではありません.戦略モードの目的はアルゴリズムの使用と実現を分割することである.例では、アルゴリズムの使用方法は不変であり、いずれもあるアルゴリズムに基づいて計算されたボーナスの金額であり、またアルゴリズムの実現はそれぞれ異なっていて、変化しています.異なるパフォーマンスは異なる計算式に対応しています.一つのポリシーモードに基づくプログラムは少なくとも二つの部分が必要で、第一の部分はポリシークラスである.具体的なアルゴリズムを実装し、具体的な計算を行う部分である.第二の部分は環境種類のcontextで、お客様の要求を受けて、あるポリシークラスに依頼します.したがって、ユーザ名は空です. です.パスワードの長さは6ビット を下回ってはいけません.携帯電話番号はフォーマット に適合していなければなりません.
まだ戦略モードを導入していないとき、私たちのコードは次のようになります. アルゴリズムの多重性が悪く、もしもう一つのフォームが検証されるなら、私たちはこの論理をほぼ完全にコピーします. ポリシーモードのフォーム検証 である. 第3のパラメータ:チェックが通っていないときに返されるエラー情報 ポリシーモードは、組合せ、依頼、および多状態を利用して、多重条件選択 を回避することができる.は、オープン・クローズ原則を完全にサポートし、アルゴリズムを ポリシーモードのアルゴリズムは、システムの他の場所にも多重化され、多くの重複貼り付けを回避することができる. ポリシーパターンは、組み合わせと委託
ポリシーモードでボーナスを計算します.
ボーナスの支給シーン:パフォーマンスがSの人の年末賞は4倍の給料で、成績はAの年末賞は3倍の給料で、成績はBの年末賞は2倍の給料で、それでは私達のプログラミングのコードです.
最初のコードの実装
var calculateBouns = function(performanceLevel, salary){
if(performanceLevel === 'S'){
return salary * 4;
}
if(performanceLevel === 'A'){
return salary*3;
}
if(performanceLevel === 'B'){
return salary*2;
}
};
calculateBouns ('B', 2000); // 4000
calculateBouns ('S', 6000); // 24000
今のこのコードはとても簡単ですが、分かりやすい問題がたくさんあります.if-else
の文が多くなり、このような文は論理分岐全体をカバーする必要がある.組合せ関数を使ってコードの再構成を行うと、私たちが最も容易に考えられる方法は、組合せ関数によってコードの再構成を行うことであり、様々なアルゴリズムを小さな関数にパッケージ化して、これらの小さな関数に良い名前が付けられています.どのアルゴリズムが使われているかを一目で知ることができます.上の使用シーンですか?コードの最適化を行います.
var performanceLevelS = function(){
return salary*4;
}
var performanceLevelA = function(){
return salary*3;
}
var performanceLevelB = function(){
return salary*2;
}
var calculateBouns = function(performanceLevel, salary){
if(performanceLevel === 'S'){
return performanceLevelS;
}
if(performanceLevel === 'A'){
return performanceLevelA;
}
if(performanceLevel === 'B'){
return performanceLevelB;
}
};
calculateBouns ('B', 2000); // 4000
上記の書き方はある程度の問題を解決しましたが、このような改善は十分に限られています.私たちの論理が複雑なとき、calculateBouns
関数はますます大きくなるかもしれません.戦略モード再構成コードを使用して、戦略モードを使ってコードを再構成できると考えています.戦略モードの意味は、一連のアルゴリズムを定義し、これらのアルゴリズムをパッケージ化して、不変の部分と変化の部分を分割することが、各設計モードの主要問題であり、戦略モードも例外ではありません.戦略モードの目的はアルゴリズムの使用と実現を分割することである.例では、アルゴリズムの使用方法は不変であり、いずれもあるアルゴリズムに基づいて計算されたボーナスの金額であり、またアルゴリズムの実現はそれぞれ異なっていて、変化しています.異なるパフォーマンスは異なる計算式に対応しています.一つのポリシーモードに基づくプログラムは少なくとも二つの部分が必要で、第一の部分はポリシークラスである.具体的なアルゴリズムを実装し、具体的な計算を行う部分である.第二の部分は環境種類のcontextで、お客様の要求を受けて、あるポリシークラスに依頼します.したがって、
context
には、あるポリシーオブジェクトに対する参照が維持される.まず策略類を使って伝統的な対象に向かう実現を模倣して、パフォーマンスの計算規則を対応する策略種類の中に入れます.var performanceLevelS = function(){};
performanceLevelS.prototype.calculate = function(salary){
return salary*4;
}
var performanceLevelA = function(){};
performanceLevelA.prototype.calculate = function(salary){
return salary*3;
}
var performanceLevelB = function(){};
performanceLevelB.prototype.calculate = function(salary){
return salary*2;
}
ボーナスの種類を定義します.var Bonus = function(){
this.strategy = null;
this.salary = null;
};
Bonus.prototype.setSalary = function(salary){
this.salary = salary;
}
Bonus.prototype.setStrategy = function(strategy){
this.strategy = strategy;
}
Bonus.prototype.getBonus = function(){
return this.strategy.calculate(this.salary);
}
戦略モードの考えを見ています.一連のアルゴリズムを定義し、それらをパッケージ化して、お互いに交換することができます.私たちは、一連のアルゴリズムを定義し、それぞれをポリシークラスにパッケージ化し、アルゴリズムをポリシークラスの内部にパッケージ化する方法で、クライアントがcontext
に対して要求を開始し、Context
は常に要求をこれらのポリシーオブジェクトの中間のいずれかに委託して計算する.残りのコードをどうやって完了するかについては、まずbonus
オブジェクトを作成し、bonusオブジェクトに元のデータを設定し、その後、あるボーナス計算のポリシーオブジェクトをbonus
オブジェクトの内部に入力して保存します.bonus.getBonus
を呼び出した場合、bonus
オブジェクト自体は計算する能力がありません.前に保存したポリシーの対象に依頼します.var bonus = new Bonus();
bonus.setSalary(1000); //
bonus.setStrategy (new performanceLevelA ()); //
console.log(bonus.getBonus());
JavaScriptバージョンに対するポリシーモード上のコードは、従来のオブジェクト指向言語を模倣して実装されていますが、実際にはJavaScript
言語では関数も対象ですので、最も簡単で直接的な方法はstrategy
を関数として指定することです.var strategis = {
"S":function(salary){
return salary * 4;
}
"A":function(salary){
return salary * 3;
}
"B":function(salary){
return salary * 2;
}
};
同様に、context
もBonus
クラスで識別しなければならない必要はありません.私たちは相変わらずcalculateBonus
関数を使ってcontext
としてユーザの要求を受け入れています.var strategis = {
"S":function(salary){
return salary * 4;
}
"A":function(salary){
return salary * 3;
}
"B":function(salary){
return salary * 2;
}
};
var calculateBonus = function(level, salary){
console.log(calculateBonus('S'),20000) // 80000
}
戦略モードを通してコードの再構成を行い,元の手順における大きな部分の条件分岐文を除去した.多くの計算に関する論理はcontext
においてはなく、ポリシーオブジェクトに分布しており、context
は計算能力がない代わりに、この職責をあるポリシーオブジェクトに委託している.各ポリシーオブジェクトが担当するアルゴリズムは、それぞれのオブジェクトの内部にカプセル化され、従来の多形に少し向かうため、各ポリシーオブジェクトは互いに以前に交換可能である.フォームの検証は登録ページを書くと仮定します.登録ボタンをクリックする前に、いくつかのチェックロジックを追加します.まだ戦略モードを導入していないとき、私たちのコードは次のようになります.
var registerForm = document.getElementById('registerForm');
registerForm.onsubmit = function(){
if(registerForm.userName.value === ''){
alert(' ');
return false;
}
if(registerForm.password.value.length < 6){
alert(' 6 ');
return false;
}
if(!/(^1[3|5|8]{9}$)/.test(registerForm.phoneNumber.value) ){
alert(' ');
return false;
}
}
これは最も簡単で一般的な符号化方式ですが、ボーナス計算の最初のテンプレートと同じ欠点があります.registerForm.onsubmit
関数は比較的に大きいです.特にチェックしたいテーブルが比較的責任がある場合、多くのif-else
文が含まれています.これらの語句は現在の検査規則をカバーする必要があります.registerForm.onsubmit
関数は弾力性に欠けています.新しい検査規則を追加する場合、または6をパスワード8ビットに変更する場合、関数の内部に深く入り込んで実現しなければなりません.開閉原則に違反しました.var strategies = {
isNotEmpty:function(value, errorMsg){ //
if(value === ''){
return errorMsg;
}
},
minLength:function(value, length, errorMsg){ //
if(value.length < length){
return errorMsg;
}
},
isMobile:function(value, errorMsg){
if(!/(^1[3|5|8]{9}$)/.test(value)){
return errorMsg;
}
}
}
各アルゴリズムを簡単にパッケージ化し、後続の呼び出しに便利を提供するため、validator
クラスをcontext
として実現し、ユーザの要求を受信し、strategy
オブジェクトに委託するつもりです.var validataFunc = function(){
var validator = new Validator();
//
validator.add(registerForm.userName, 'isNotEmpty', ' ');
validator.add(registerForm.password, 'minLength:6', ' 6 ');
validator.add(registerForm.phoneNumber, 'isMobile', ' ');
var errorMsg = validator.start(); //
return errorMsg; //
}
var registerForm = document.getElementById('registerForm');
registerForm.onsubmit = function(){ // errorMsg ,
if(errorMsg){
alert(errorMsg);
return false;//
}
}
コードでは、まずvalidator
オブジェクトを作成し、validator.add
方法でvalidator
オブジェクトにいくつかのチェックルールを追加します.validator.add
方法では、3つのパラメータを受け付けますが、以下のように説明しますか?validator.add(registerForm.password, 'minLength:6', ' 6 ');
registerForm.password
は、検査に参加するinputの入力ブロックminLength:6
はコロンで区切られた文字列で、コロンの前はアルゴリズムの名前で、コロンの後は私達が入るパラメータです.追加の情報が必要でなければ、コロンを追加せずにアルゴリズムの名前を直接入力してください.validator
オブジェクトに一連のチェックルールを追加した後、validator.start()
方法を呼び出して検証を開始し、この方法が正確なerrorMsg
の値を返すと、onsubmit
方法はfalse
に戻ってフォームの提出を阻止する.最後にValidator
クラスの実装を構築しましょう.var Validator = function (){
this.cache = []; //
}
Validator.prototype.add = function(dom, rule, erroMsg){
for(var i = 0, validataFunc; validataFunc = this.cache[i++]){
var msg = validataFunc();
if(msg){
return msg;
}
}
}
私たちはルールを追加したいです.簡単なフォーム検証を配置するだけで、これらのルールはプログラムのどこにも簡単に多重化できます.プラグインの形で他の項目に移植することもできます.パスワードの長さを変更したいなら、10桁以下ではいけません.validator.add(registerForm.password, 'minLength:10', ' 10 ')
を呼び出します.テキストボックスに複数のチェックルールを追加します.テキストボックスに複数のチェックルールを追加したいなら、例えば、入力したユーザ名が空ではなく、長さが10桁以下であることを確認したいですが、どうやってチェックしますか?validator.add(registerForm.userName, [
{
strategy:'isNotEmpty',
errorMsg:' '
}, {
strategy:'minLength:10',
errorMsg:' 10 '
}
]);
//
var strategies = {
isNotEmpty:function(value, errorMsg){
if(value === ''){
return errorMsg;
}
},
minLength:function(value, length, errorMsg){
//
if(value.length < length){
return errorMsg;
}
},
isMobile:function(value, errorMsg){
if(!/(^1[3|5|8]{9}$)/.test(value)){
return errorMsg;
}
}
}
var Validator = function (){
this.cache = []; //
}
Validator.prototype.add = function(dom, rules){
var self = this;
for(var i = 0, rule; rule = rules[i++]){
(function(rule){
var strategyAry = rule.strategy.split(':');
var errorMsg = rule.errorMsg;
self.cache.push(function(){
var strategy = strategyAry.shift();
strategyAry.unshift(dom.value);
strategyAry.push(errorMsg);
return strategies[strategy].apply(dom, strategyAry);
});
})(rule)
}
};
Validator.prototype.start = function(){
for(var i = 0, validataFunc; validataFunc = this.cache[i++]){
var msg = validataFunc();
if(msg){
return msg;
}
}
};
//
var registerForm = document.getElementById('registerForm');
var validataFunc = function(){
var validator = new Validator();
validator.add(registerForm.userName,[{
strategy: 'isNotEmpty',
errorMsg: ' '
},
{
strategy: 'minLength:10',
errorMsg: ' 10'
}]);
validator.add(registerForm.password,[{
strategy: 'minLength:6',
errorMsg: ' 6'
}]);
validator.add(registerForm.phoneNumber,[{
strategy: 'isMobile',
errorMsg: ' '
}]);
var errorMsg = validator.start();
return errorMsg;
}
registerForm.onsubmit = function(){
var errorMsg = validataFunc();
if(errorMsg){
alert(errorMsg);
return false;
}
}
ポリシーモードの利点:strategy
に独立してパッケージ化することができ、アルゴリズム間の切り替えが容易であり、分かりやすく、拡張が容易である.Context
を利用してアルゴリズムを実行する能力を持ち、これも継承のためのより便利な代替案である.