Javascriptで戦略パターンを実装する方法

Javascriptで戦略パターンを実装する方法

概要

戦略パターンは、JavaScript デザイン パターンにおける動作デザイン パターンです。

意味:

一連のアルゴリズムを定義し、これらの各アルゴリズムを戦略クラス(メソッド)にカプセル化し、変更されない部分と可変部分を分離すると、これらのアルゴリズムを互いに置き換えることができます。

俗語による説明:

実際、いわゆる戦略モードは、異なる戦略に従って異なるメソッドを実行することを指し、if-else 分岐判断と非常によく似ていますが、戦略モードは複数の条件判断ステートメントを解決するために使用されます。

コードの実装

必要:

年末が近づいてきたため、ある企業は年末ボーナスを前倒しで支給することを決めました。しかし、年末ボーナスの計算には一定のルールがあり、年末ボーナスの額は業績評価と密接に関係しています。そのため、ある企業の年末ボーナス計画は次のようになります。

業績評価がSの従業員の場合、年末ボーナスは月給の4倍になります。

業績評価がAの従業員の場合、年末ボーナスは月給の3倍になります。

業績評価がBの従業員の場合、年末ボーナスは月給の2倍になります。

これを見て、プログラムを書き始めることができます。一般的に、ほとんどのコードは次のようになります。

関数 calculateBonus(レベル, 給与){
    if(レベル === 'S'){
        給与の返還*4
    }
    
    if(レベル === 'A'){
        給与返還*3
    }

    if(レベル === 'B'){
        給与返還*2
    }
}

console.log(calculateBonus("S",14000)); //56000
console.log(calculateBonus("A",10000)); //30000
console.log(calculateBonus("B",5000)); //10000

上記のコードを使用して現在のニーズを解決することに問題はありませんが、プログラム設計の観点から、上記のコードはまだ最適化できます。この方法は比較的大きく、分岐判断が多く、柔軟性に欠けるため、年末ボーナスプランが変更された場合、Cプランを追加する必要がありますか?メソッドに分岐判断を追加する必要がありますか?これはオープン・クローズ原則に違反します。

最適化:

var 戦略 = {
    "S": 関数(給与){
        給与返還*4
    },
    "A": 関数(給与){
        給与の返還*3
    },
    "B": 関数(給与){
        給与返還*2
    }
}

var calculateBonus =function(level,salary){
    リターン戦略[レベル](給与);
} 
console.log(calculateBonus("S",14000)); //56000
console.log(calculateBonus("A",10000)); //30000
console.log(calculateBonus("B",5000)); //10000

上記のコードを最適化した後、戦略パターンを使用してコードを変換します。戦略オブジェクトを定義し、calculateBonus がユーザーが渡したレベルと給与に応じて年末ボーナスの金額を計算できることがわかります。変換後、コードの構造はより簡潔になります。

Web 開発では、ログイン ページの登録機能とログイン機能はすべてフォームの送信を必要としますが、送信プロセス中に検証とスクリーニングを実行する必要があり、検証ルールを満たさないものは直接送信されません。デザイン パターンを学習する前は、検証も上記と同じで、複数の if ブランチを使用していましたが、現在は戦略パターンを使用してフォーム検証を実装しています。

<!DOCTYPE html>
<html lang="ja">
<ヘッド>
    <メタ文字セット="UTF-8">
    <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
    <meta http-equiv="X-UA-compatible" content="ie=edge">
    <title>ドキュメント</title>
</head>
<本文>
        <フォームアクション="http://xxx.com/register" id="registerForm" メソッド="post">
            ユーザー名を入力してください: <input type="text" name="userName"/ >
            パスワードを入力してください: <input type="text" name="password"/ >
            電話番号を入力してください: <input type="text" name="phoneNumber"/ >
            <button>送信</button>
        </フォーム>
</本文>
<スクリプト>
        // 戦略クラスのアルゴリズム検証ルールを定義する var strategies = {
        isNonEmpty: 関数(値、エラーメッセージ){
            if ( 値 === '' ) {
                errorMsg を返します。
            }
        },
        minLength: 関数(値、長さ、エラーメッセージ){
            (値の長さ<長さ)の場合{
                errorMsg を返します。
            }
        },
        isMobile: 関数(値、エラーメッセージ){
            if ( !/(^1[3|5|8][0-9]{9}$)/.test( 値 ) ){
                errorMsg を返します。
            }
        }
    };
    //バリデータクラス var Validator = function(){
        // 検証ルールを保存します this.cache = [];
    };
    //検証ルールを追加するメソッド Validator.prototype.add = function( dom, rules ){
        var self = this;
        for ( var i = 0, ルール; ルール = ルール[ i++ ]; ){
            (関数(ルール){
                //検証ルールオブジェクト内の戦略属性の値を分割します。var strategyAry = rule.strategy.split( ':' );
                var errorMsg = ルール.errorMsg;
                self.cache.push(関数(){
                    //検証ルール オブジェクトの strategy 属性の最初の値を返して、それを strategy に格納します。var strategy = strategyAry.shift();
                    // 構成パラメータ strategyAry.unshift( dom.value );
                    //アセンブリパラメータ strategyAry.push( errorMsg );
                    //戦略オブジェクトの実行メソッドを見つけて、それをキャッシュ変数に格納します。 return strategies[ strategy ].apply( dom, strategyAry );
                });
                console.log(戦略Ary);
            })( ルール )
        }
    };
    //検証メソッドを開始する Validator.prototype.start = function(){
        ( var i = 0, validatorFunc; validatorFunc = this.cache[ i++ ]; ){
             //ループキャッシュ実行メソッドの検証 var errorMsg = validatorFunc();
            //実行戦略オブジェクトメソッドで errorMsg が返された場合、メソッドがエラーを報告した (検証ルールに合格できなかった) ことを意味します。
            if (エラーメッセージ){
                errorMsg を返します。
            }
        }
    };

    // 検証を呼び出す var registerForm = document.getElementById( 'registerForm' );
    //検証ルールをカスタマイズするメソッドを定義する var validataFunc = function(){
        //オブジェクトをインスタンス化します var validator = new Validator();
        //検証ルールをカスタマイズvalidator.add(registerForm.userName, [{
            戦略: 'isNonEmpty'、
            errorMsg: 'ユーザー名は空にできません'
        }, {
            戦略: 'minLength:6',
            errorMsg: 'ユーザー名は 10 文字未満にすることはできません'
        }]);
        バリデーター.add( registerForm.password, [{
            戦略: 'minLength:6',
            errorMsg: 'パスワードの長さは 6 文字未満にできません'
        }]);
        //ループ内で検証を実行するメソッドを呼び出します var errorMsg = validator.start();
        errorMsg を返します。
    }
    //送信ボタンをクリックする(送信イベント)
    registerForm.onsubmit = 関数(){
        //上記のカスタム検証メソッドを実行します var errorMsg = validataFunc();
        //errorMsgが存在する場合、検証が失敗したことを意味します if (errorMsg){
            アラート ( errorMsg );
            false を返します。
        }

    };
</スクリプト>
</html>

戦略パターンを使用すると、フォーム検証における大規模な繰り返し if-else 判断などの問題を解決できます。上記のコードには詳細なコメントを付けました。デザイン パターンを学ぶには、コードを注意深く味わい、アイデアを学ぶ必要があります。とにかく、戦略パターンの主なアイデアの 1 つは、一連のアルゴリズムを定義し、パラメーターを渡し、異なるパラメーターに応じて異なるアルゴリズム ルールを実行することです。

要約する

アドバンテージ:

1. 複数の条件選択ステートメントを回避するために、組み合わせ、委任、およびポリモーフィズムのテクノロジとアイデアを使用します。

2. アルゴリズムを独立した戦略クラスにカプセル化し、切り替え、理解、拡張を容易にします。

3. 戦略パターンはシステムの他の部分で再利用できるため、コピーと貼り付けの作業を繰り返す必要がなくなります。

欠点:

1. 多くの戦略クラスまたは戦略オブジェクトがプログラムに追加されます。

2. 戦略クラスを使用する場合は、すべての戦略アルゴリズムを明確に理解している必要があります。そうでないと、選択方法がわかりません。

上記はJavaScript戦略パターンの詳細です。JavaScript戦略パターンの詳細については、123WORDPRESS.COMの他の関連記事をご覧ください。

以下もご興味があるかもしれません:
  • フォーム検証からのJavaScript戦略モードの使用の詳細な説明
  • JavaScript デザインパターン戦略パターン実装原則詳細説明
  • JSフォーム検証プラグインデータとロジック分離操作例分析[戦略モード]
  • JavaScript デザインパターン - 戦略パターンの原則と使用例
  • JS デザインパターンにおける戦略パターンの概念と使用法の分析
  • JavaScriptは非同期検証フォームを同期フォームに書き換えます
  • js がフォームを検証した後にフォームを送信する 3 つの方法の概要
  • JavaScript戦略モードを簡単にマスター
  • JavaScript 戦略パターンを使用してフォームを検証する方法

<<:  LinuxにDockerをインストールする(非常に簡単なインストール方法)

>>:  本番環境でのMySQLパラメータsql_safe_updatesの使用に関する詳細な説明

推薦する

MySQL パーティションテーブルの正しい使用方法

MySQL パーティションテーブルの概要数億、あるいは数十億ものレコードを格納するテーブルに遭遇する...

CSSのさまざまな背景、使用シナリオ、テクニックの詳細な分析

この記事はGitHub https://github.com/qq449245884/xiaozhi...

JavaScript の非同期処理で待機時間を節約できますか?

JavaScriptで非同期実行の結果を同期的に取得するには、 for ループ内でawaitを使用...

React NativeとiOSの相互作用の詳細な説明

目次前提条件RNはiOSに価値を渡す方法1: ネイティブに値を通常通り渡す方法2: コールバック関数...

MySQL クエリ キャッシュのグラフィカルな説明

目次1. 原則の概要クエリキャッシュシステム変数1. クエリキャッシュを持つ2. クエリキャッシュ制...

初心者がHTMLタグを学ぶ(1)

初心者は、いくつかの HTML タグを理解することで HTML を学習できます。この入門書は、初心者...

js を使ってシンプルな虫眼鏡効果を実現

この記事の例では、参考までに簡単な虫眼鏡効果を実現するためのjsの具体的なコードを共有しています。具...

ネイティブ js を使用してライブ バレット スクリーンのスクロール効果をシミュレートします。

目次1. 基本原則2. 特定のコード要約する1. 基本原則まず、生放送エリアを10の部分に分割し(個...

Ubuntu で G++ を使用して CPP ファイルをコンパイルする

g++ を使用して初めて cpp ファイルをコンパイルしたとき、未定義の参照エラーが報告されました。...

Html+CSS フローティング広告ストリップの実装

1.html部分コードをコピーコードは次のとおりです。 <!DOCTYPE html> ...

Tomcatサーバーのセキュリティ設定方法

Tomcat は、Java Community Process を通じて Sun が開発した、広く使...

JavaScript で知らない Object.entries の使い方

目次序文1. 共通オブジェクトを反復処理するには for...of を使用します2. 通常のオブジェ...

MySQL 実験: explain を使用してインデックスの傾向を分析する

概要インデックス作成は、MySQL で習得しなければならないスキルであり、MySQL クエリの効率を...

CSS3 境界効果

CSSとは# CSS (Cascading Style Sheets の略) は、「カスケーディング...

MySQL コピーテーブルと許可分析の 3 つの実装方法

テーブルを素早くコピーする方法まず、テーブル db1.t を作成し、1000 行のデータを挿入します...