検索
ホームページウェブフロントエンドjsチュートリアルデザインパターンの戦略パターンをフロントエンドで使用する方法

デザインパターンの戦略パターンをフロントエンドで使用する方法

May 24, 2018 am 09:50 AM
フロントエンドどうやってデザインパターン

今回はデザインパターン戦略パターンをフロントエンドで使用する方法と、デザインパターンの戦略パターンをフロントエンドで使用する際の注意点についてお届けします。実際のケースを見てみましょう。

ストラテジーモードとは何ですか?

GoF 4 兄弟による古典的な「デザイン パターン」では、戦略パターンは次のように定義されています。

一連のアルゴリズムを定義し、それらを 1 つずつカプセル化して、互換性を持たせる。

上記の文は文字通り非常に単純です。しかし、開発プロセスにそれをどのように適用するかは、定義が 1 つだけではまだわかりにくいです。著者がかつて取り組んだ小売業者の購買、販売、在庫システムを例に挙げます。

あるスーパーマーケットでは、調査と分析の後、いくつかのプロモーション戦略を策定しました。
  1. は 10 割引です。 100以上の購入

  2. 200以上の購入で30割引

  3. 300以上の購入で50割引

  4. 。 。 。

レジソフトのインターフェースはこんな感じです(簡単な図):

デザインパターンの戦略パターンをフロントエンドで使用する方法

実際の消費額はどのように計算すればよいでしょうか?

最初の実装は次のとおりです:

//方便起见,我们把各个促销策略定义为枚举值:0,1,2...
var getActualTotal = function(onSaleType,originTotal){
    if(onSaleType===0){
        return originTotal-Math.floor(originTotal/100)*10
    }
    if(onSaleType===1){
        return originTotal-Math.floor(originTotal/200)*30
    }
    if(onSaleType===0){
        return originTotal-Math.floor(originTotal/300)*50
    }
}
getActualTotal(1,2680); //2208

上記のコードは非常に単純ですが、その欠点も明らかです。私の完全削減戦略が徐々に増加するにつれて、getActualTotal 関数はますます大きくなり、if の判断が満載になります。注意しないと間違いを犯しやすくなります。 。 getActualTotal函数会越变越大,而且充满了if判断,稍一疏忽就容易弄错。

OK,有人说我很懒,虽然这样不够优雅但并不影响我的使用,毕竟满减策略再多也多不到哪去。
我只能说,需求永远不是程序员定的。。这时,市场人员说我们新版程序添加了会员功能,我们需要支持以下的促销策略:

会员促销策略:
  1. 会员充300返60,且首单打9折

  2. 会员充500返100,且首单打8折

  3. 会员充1000返300,且首单打7折

  4. ...

这个时候,如果你还在原先的getActualTotal函数中继续添加if判断,我想如果你的领导review你这段代码,可能会怀疑自己当初怎么把你招进来。。

OK,我们终于下定决心要重构促销策略的代码,我们可以这么做:

var vipPolicy_0=function(originTotal){
    return originTotal-Math.floor(originTotal/100)*10
}
var vipPolicy_1=function(originTotal){
    return originTotal-Math.floor(originTotal/200)*30
}
...
//会员充1000返300
var vipPolicy_10=function(account,originTotal){
    if(account===0){
        account+=1300;
        return originTotal*0.9
    }else{
        account+=1300;
        return originTotal;
    }
    return originTotal-Math.floor(originTotal/200)*30
}
...
var vipPolicy_n=function(){
    ...
}
var getActualTotal=function(onSaleType,originTotal,account){
    switch(onSaleType){
        case 0:
            return vipPolicy_0(originTotal);
        case 1:
            return vipPolicy_0(originTotal);
        ...
        case n:
            return ...
        default:
            return originTotal;
    }
}

好了,现在我们每种策略都有自己独立的空间了,看起来井井有条。但是还有两个问题没有解决:

  1. 随着促销策略的增加,getActualTotal的代码量依然会越来越大

  2. 系统缺乏弹性,如果需要增加一种策略,那么除了添加一个策略函数,还需要修改switch...case..语句

让我们再来回顾一下策略模式的定义:

定义一系列的算法,把它们一个个封装起来,并且使它们可互相替换

在我们的例子中,每种促销策略的实现方式是不一样的,但我们最终的目的都是为了求得实际金额。策略模式可以把我们对促销策略的算法一个个封装起来,并且使它们可互相替换而不影响我们对实际金额的求值,这正好是我们所需要的。

下面我们用策略模式来重构上面的代码:

var policies={
    "Type_0":function(originTotal){
        return originTotal-Math.floor(originTotal/100)*10 
    },
    "Type_1":function(originTotal){
        return originTotal-Math.floor(originTotal/200)*30 
    },
    ...
    "Type_n":function(originTotal){
        ... 
    }
}
var getActualTotal=function(onSaleType,originTotal,account){
    return policies["Type_"+onSaleType](originTotal,account)
}
//执行
getActualTotal(0,2680.00);//2208

分析上面的代码我们发现,不管促销策略如何增加,getActualTotal函数完全不需要再变化了。我们要做的,就是增加新策略的函数而已。

通过策略模式的代码,我们消除了让人反胃的大片条件分支语句,getActualTotal

OK、これは十分に洗練されていないと言う人もいますが、結局のところ、完全な削減戦略をどれだけ使用しても十分ではありません。
言えることは、要件は決してプログラマーによって決定されるものではないということです。 。現時点では、市場スタッフは、プログラムの新しいバージョンにはメンバーシップ機能が追加されており、次のプロモーション戦略をサポートする必要があると述べました:

メンバープロモーション戦略:
  1. メンバーに 300 をチャージすると 60 が戻ってくる、そして最初の注文で 10% オフ🎜🎜🎜🎜メンバーは 500 100 をチャージすると、初回注文で 20% オフになります🎜🎜🎜🎜 メンバーとして 1000 をチャージすると、300 がバックされ、さ​​らに初回注文では 30% オフになります🎜🎜🎜 🎜...🎜🎜🎜🎜この時点で、まだ元の getActualTotal を使用している場合は、引き続き if 判定を関数に追加してください。リーダーがレビューしてくれると思います。コード、彼はそもそもなぜあなたを雇ったのか疑問に思うかもしれません。 。 🎜🎜OK、ついにプロモーション戦略のコードをリファクタリングすることにしました。これを行うことができます: 🎜
    //方便起见,我们把各个促销策略定义为枚举值:0,1,2...
    var getActualTotal = function(onSaleType,originTotal){
        if(onSaleType===0){
            return originTotal-Math.floor(originTotal/100)*10
        }
        if(onSaleType===1){
            return originTotal-Math.floor(originTotal/200)*30
        }
        if(onSaleType===0){
            return originTotal-Math.floor(originTotal/300)*50
        }
    }
    getActualTotal(1,2680); //2208
    🎜 さて、各戦略には独自の独立したスペースがあり、よく整理されているように見えます。しかし、まだ解決されていない問題が 2 つあります: 🎜🎜🎜🎜 プロモーション戦略の増加に伴い、getActualTotal のコード量は依然として増大するでしょう 🎜🎜🎜🎜 システムは柔軟性に欠けています。戦略を追加する必要がある場合は、戦略関数の追加に加えて、switch...case.. ステートメントも変更する必要があります🎜🎜🎜🎜戦略の定義を確認してみましょうパターン: 🎜🎜一連のアルゴリズムを定義します。これらは 1 つずつカプセル化され、交換可能になります。この例では、各プロモーション戦略の実装は異なりますが、最終的な目標は実際の量を見つけることです。戦略パターンは、プロモーション戦略のアルゴリズムを 1 つずつカプセル化し、実際の金額の評価に影響を与えることなく互換性を持たせることができます。これはまさに私たちが必要としているものです。 🎜🎜 戦略パターンを使用して上記のコードを再構築しましょう: 🎜
    var vipPolicy_0=function(originTotal){
        return originTotal-Math.floor(originTotal/100)*10
    }
    var vipPolicy_1=function(originTotal){
        return originTotal-Math.floor(originTotal/200)*30
    }
    ...
    //会员充1000返300
    var vipPolicy_10=function(account,originTotal){
        if(account===0){
            account+=1300;
            return originTotal*0.9
        }else{
            account+=1300;
            return originTotal;
        }
        return originTotal-Math.floor(originTotal/200)*30
    }
    ...
    var vipPolicy_n=function(){
        ...
    }
    var getActualTotal=function(onSaleType,originTotal,account){
        switch(onSaleType){
            case 0:
                return vipPolicy_0(originTotal);
            case 1:
                return vipPolicy_0(originTotal);
            ...
            case n:
                return ...
            default:
                return originTotal;
        }
    }
    🎜 上記のコードを分析すると、プロモーション戦略がどのように増加しても、getActualTotal 関数はまったく変更する必要がないことがわかりました。 。新しい戦略の機能を追加するだけです。 🎜🎜 ストラテジ パターン コードを通じて、胃が痛むような条件分岐ステートメントを排除します。getActualTotal 自体には計算能力はありませんが、計算をストラテジ関数に委任します。 🎜🎜これから、戦略パターン実装の重要なポイントを要約できます: 🎜🎜🎜🎜変化するアルゴリズムを独立した戦略関数にカプセル化し、特定の計算を担当します🎜
  2. 顧客のリクエストを受け付け、そのリクエストを特定の戦略関数に委任する

UML図で表すと以下のようになります。上の写真を見て、はっきりと理解できましたか?それなら急いでストラテジーモードに挑戦してください!
デザインパターンの戦略パターンをフロントエンドで使用する方法

参考書籍:


『デザインパターン:再利用可能
    オブジェクト指向
  1. ソフトウェアの基礎』

    『Dahuaデザインパターン』
  2. デザインパターンと開発実践》
  3. 私は数年フロントエンド開発をしていますが、デザインパターンを深く勉強してまとめたことがありませんでした。建築関連の仕事をすることが多くなるにつれ、デザインパターンが自分の進むべき道において障害になっていると感じることが増えてきました。したがって、今日から古典的なデザイン パターンといくつかの主要なオブジェクト指向原則を深く研究し、要約することから始めましょう。

    初日の今日は、まずストラテジーモードについて話しましょう。
ストラテジーモードとは何ですか?
GoF 4 兄弟による古典的な「デザイン パターン」では、戦略パターンは次のように定義されています。

一連のアルゴリズムを定義し、それらを 1 つずつカプセル化して、互換性を持たせる。

上記の文は文字通り非常に単純です。しかし、開発プロセスにそれをどのように適用するかは、定義が 1 つだけではまだわかりにくいです。著者がかつて取り組んだ小売業者の購買、販売、在庫システムを例に挙げます。

あるスーパーマーケットでは、調査と分析の後、いくつかのプロモーション戦略を策定しました。

は 10 割引です。 100以上の購入
  1. 200以上の購入で30割引

  2. 300以上の購入で50割引

  3. 。 。 。

  4. レジソフトのインターフェースはこんな感じです(簡単な図):

実際の消費額はどのように計算すればよいでしょうか?

最初の実装は次のとおりです: デザインパターンの戦略パターンをフロントエンドで使用する方法

//方便起见,我们把各个促销策略定义为枚举值:0,1,2...
var getActualTotal = function(onSaleType,originTotal){
    if(onSaleType===0){
        return originTotal-Math.floor(originTotal/100)*10
    }
    if(onSaleType===1){
        return originTotal-Math.floor(originTotal/200)*30
    }
    if(onSaleType===0){
        return originTotal-Math.floor(originTotal/300)*50
    }
}
getActualTotal(1,2680); //2208
上記のコードは非常に単純ですが、その欠点も明らかです。私の完全削減戦略が徐々に増加するにつれて、getActualTotal 関数はますます大きくなり、if の判断が満載になります。注意しないと間違いを犯しやすくなります。 。

OK、これは十分に洗練されていないと言う人もいますが、結局のところ、完全な削減戦略をどれだけ使用しても十分ではありません。

要件は決してプログラマによって決定されるものではないとしか言​​えません。 。現時点では、市場スタッフは、プログラムの新しいバージョンにはメンバーシップ機能が追加されており、次のプロモーション戦略をサポートする必要があると述べました:

メンバープロモーション戦略: getActualTotal函数会越变越大,而且充满了if判断,稍一疏忽就容易弄错。

OK,有人说我很懒,虽然这样不够优雅但并不影响我的使用,毕竟满减策略再多也多不到哪去。
我只能说,需求永远不是程序员定的。。这时,市场人员说我们新版程序添加了会员功能,我们需要支持以下的促销策略:

会员促销策略:
  1. 会员充300返60,且首单打9折

  2. 会员充500返100,且首单打8折

  3. 会员充1000返300,且首单打7折

  4. ...

这个时候,如果你还在原先的getActualTotal函数中继续添加if判断,我想如果你的领导review你这段代码,可能会怀疑自己当初怎么把你招进来。。

OK,我们终于下定决心要重构促销策略的代码,我们可以这么做:

var vipPolicy_0=function(originTotal){
    return originTotal-Math.floor(originTotal/100)*10
}
var vipPolicy_1=function(originTotal){
    return originTotal-Math.floor(originTotal/200)*30
}
...
//会员充1000返300
var vipPolicy_10=function(account,originTotal){
    if(account===0){
        account+=1300;
        return originTotal*0.9
    }else{
        account+=1300;
        return originTotal;
    }
    return originTotal-Math.floor(originTotal/200)*30
}
...
var vipPolicy_n=function(){
    ...
}
var getActualTotal=function(onSaleType,originTotal,account){
    switch(onSaleType){
        case 0:
            return vipPolicy_0(originTotal);
        case 1:
            return vipPolicy_0(originTotal);
        ...
        case n:
            return ...
        default:
            return originTotal;
    }
}

好了,现在我们每种策略都有自己独立的空间了,看起来井井有条。但是还有两个问题没有解决:

  1. 随着促销策略的增加,getActualTotal的代码量依然会越来越大

  2. 系统缺乏弹性,如果需要增加一种策略,那么除了添加一个策略函数,还需要修改switch...case..

メンバーに 300 をチャージすると 60 が戻ってくる、そして最初の注文で 10% オフ

🎜🎜メンバーは 500 100 をチャージすると、初回注文で 20% オフになります🎜🎜🎜🎜 メンバーとして 1000 をチャージすると、300 がバックされ、さ​​らに初回注文では 30% オフになります🎜🎜🎜 🎜...🎜🎜🎜🎜この時点で、まだ元の getActualTotal を使用している場合は、引き続き if 判定を関数に追加してください。リーダーがレビューしてくれると思います。コード、彼はそもそもなぜあなたを雇ったのか疑問に思うかもしれません。 。 🎜🎜OK、ついにプロモーション戦略のコードをリファクタリングすることにしました。これを行うことができます: 🎜
var policies={
    "Type_0":function(originTotal){
        return originTotal-Math.floor(originTotal/100)*10 
    },
    "Type_1":function(originTotal){
        return originTotal-Math.floor(originTotal/200)*30 
    },
    ...
    "Type_n":function(originTotal){
        ... 
    }
}
var getActualTotal=function(onSaleType,originTotal,account){
    return policies["Type_"+onSaleType](originTotal,account)
}
//执行
getActualTotal(0,2680.00);//2208
🎜 さて、各戦略には独自の独立したスペースがあり、よく整理されているように見えます。しかし、まだ解決されていない問題が 2 つあります: 🎜🎜🎜🎜 プロモーション戦略の増加に伴い、getActualTotal のコード量は依然として増大するでしょう 🎜🎜🎜🎜 システムは柔軟性に欠けています。ストラテジーを追加する必要がある場合は、ストラテジー関数の追加に加えて、switch...case.. ステートメントも変更する必要があります🎜🎜🎜🎜ストラテジー パターンの定義を確認してみましょうもう一度:🎜
定义一系列的算法,把它们一个个封装起来,并且使它们可互相替换

在我们的例子中,每种促销策略的实现方式是不一样的,但我们最终的目的都是为了求得实际金额。策略模式可以把我们对促销策略的算法一个个封装起来,并且使它们可互相替换而不影响我们对实际金额的求值,这正好是我们所需要的。

下面我们用策略模式来重构上面的代码:

var policies={
    "Type_0":function(originTotal){
        return originTotal-Math.floor(originTotal/100)*10 
    },
    "Type_1":function(originTotal){
        return originTotal-Math.floor(originTotal/200)*30 
    },
    ...
    "Type_n":function(originTotal){
        ... 
    }
}
var getActualTotal=function(onSaleType,originTotal,account){
    return policies["Type_"+onSaleType](originTotal,account)
}
//执行
getActualTotal(0,2680.00);//2208

分析上面的代码我们发现,不管促销策略如何增加,getActualTotal函数完全不需要再变化了。我们要做的,就是增加新策略的函数而已。

通过策略模式的代码,我们消除了让人反胃的大片条件分支语句,getActualTotal本身并没有计算能力,而是将计算全权委托给了策略函数。

由此我们可以总结出策略模式实现的要点:

  1. 将变化的算法封装成独立的策略函数,并负责具体的计算

  2. 委托函数,该函数接受客户请求,并将请求委托给某一个具体的策略函数

用一张UML图表示如下:
デザインパターンの戦略パターンをフロントエンドで使用する方法

怎么样?现在看到上面这张图是不是有了了然于胸的感觉?那就赶紧去试一试策略模式吧!

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

怎样使用JS+H5实现微信摇一摇

如何对微信小程序进行开发

以上がデザインパターンの戦略パターンをフロントエンドで使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
JavaScript in Action:実際の例とプロジェクトJavaScript in Action:実際の例とプロジェクトApr 19, 2025 am 12:13 AM

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

JavaScriptとWeb:コア機能とユースケースJavaScriptとWeb:コア機能とユースケースApr 18, 2025 am 12:19 AM

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

JavaScriptエンジンの理解:実装の詳細JavaScriptエンジンの理解:実装の詳細Apr 17, 2025 am 12:05 AM

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

Python vs. JavaScript:学習曲線と使いやすさPython vs. JavaScript:学習曲線と使いやすさApr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

Python vs. JavaScript:コミュニティ、ライブラリ、リソースPython vs. JavaScript:コミュニティ、ライブラリ、リソースApr 15, 2025 am 12:16 AM

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

C/CからJavaScriptへ:すべてがどのように機能するかC/CからJavaScriptへ:すべてがどのように機能するかApr 14, 2025 am 12:05 AM

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

JavaScriptエンジン:実装の比較JavaScriptエンジン:実装の比較Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

ブラウザを超えて:現実世界のJavaScriptブラウザを超えて:現実世界のJavaScriptApr 12, 2025 am 12:06 AM

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境