デザインパターンの戦略パターンをフロントエンドで使用する方法
今回はデザインパターンの戦略パターンをフロントエンドで使用する方法と、デザインパターンの戦略パターンをフロントエンドで使用する際の注意点についてお届けします。実際のケースを見てみましょう。
ストラテジーモードとは何ですか?
GoF 4 兄弟による古典的な「デザイン パターン」では、戦略パターンは次のように定義されています。
一連のアルゴリズムを定義し、それらを 1 つずつカプセル化して、互換性を持たせる。
上記の文は文字通り非常に単純です。しかし、開発プロセスにそれをどのように適用するかは、定義が 1 つだけではまだわかりにくいです。著者がかつて取り組んだ小売業者の購買、販売、在庫システムを例に挙げます。
あるスーパーマーケットでは、調査と分析の後、いくつかのプロモーション戦略を策定しました。
は 10 割引です。 100以上の購入
200以上の購入で30割引
300以上の購入で50割引
。 。 。
レジソフトのインターフェースはこんな感じです(簡単な図):
実際の消費額はどのように計算すればよいでしょうか?
最初の実装は次のとおりです:
//方便起见,我们把各个促销策略定义为枚举值: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,有人说我很懒,虽然这样不够优雅但并不影响我的使用,毕竟满减策略再多也多不到哪去。
我只能说,需求永远不是程序员定的。。这时,市场人员说我们新版程序添加了会员功能,我们需要支持以下的促销策略:
会员促销策略:
会员充300返60,且首单打9折
会员充500返100,且首单打8折
会员充1000返300,且首单打7折
...
这个时候,如果你还在原先的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; } }
好了,现在我们每种策略都有自己独立的空间了,看起来井井有条。但是还有两个问题没有解决:
随着促销策略的增加,
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
言えることは、要件は決してプログラマーによって決定されるものではないということです。 。現時点では、市場スタッフは、プログラムの新しいバージョンにはメンバーシップ機能が追加されており、次のプロモーション戦略をサポートする必要があると述べました: メンバープロモーション戦略:
-
メンバーに 300 をチャージすると 60 が戻ってくる、そして最初の注文で 10% オフ🎜🎜🎜🎜メンバーは 500 100 をチャージすると、初回注文で 20% オフになります🎜🎜🎜🎜 メンバーとして 1000 をチャージすると、300 がバックされ、さらに初回注文では 30% オフになります🎜🎜🎜 🎜...🎜🎜🎜🎜この時点で、まだ元の
getActualTotal
を使用している場合は、引き続きif
判定を関数に追加してください。リーダーがレビューしてくれると思います。コード、彼はそもそもなぜあなたを雇ったのか疑問に思うかもしれません。 。 🎜🎜OK、ついにプロモーション戦略のコードをリファクタリングすることにしました。これを行うことができます: 🎜🎜 さて、各戦略には独自の独立したスペースがあり、よく整理されているように見えます。しかし、まだ解決されていない問題が 2 つあります: 🎜🎜🎜🎜 プロモーション戦略の増加に伴い、//方便起见,我们把各个促销策略定义为枚举值: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
のコード量は依然として増大するでしょう 🎜🎜🎜🎜 システムは柔軟性に欠けています。戦略を追加する必要がある場合は、戦略関数の追加に加えて、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
自体には計算能力はありませんが、計算をストラテジ関数に委任します。 🎜🎜これから、戦略パターン実装の重要なポイントを要約できます: 🎜🎜🎜🎜変化するアルゴリズムを独立した戦略関数にカプセル化し、特定の計算を担当します🎜 顧客のリクエストを受け付け、そのリクエストを特定の戦略関数に委任する
UML図で表すと以下のようになります。上の写真を見て、はっきりと理解できましたか?それなら急いでストラテジーモードに挑戦してください!
『デザインパターン:再利用可能
- オブジェクト指向
- ソフトウェアの基礎』『Dahuaデザインパターン』
-
-
私は数年フロントエンド開発をしていますが、デザインパターンを深く勉強してまとめたことがありませんでした。建築関連の仕事をすることが多くなるにつれ、デザインパターンが自分の進むべき道において障害になっていると感じることが増えてきました。したがって、今日から古典的なデザイン パターンといくつかの主要なオブジェクト指向原則を深く研究し、要約することから始めましょう。
初日の今日は、まずストラテジーモードについて話しましょう。
- 200以上の購入で30割引
- 300以上の購入で50割引
- 。 。 。
- レジソフトのインターフェースはこんな感じです(簡単な図):
実際の消費額はどのように計算すればよいでしょうか?
最初の実装は次のとおりです:
//方便起见,我们把各个促销策略定义为枚举值: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,有人说我很懒,虽然这样不够优雅但并不影响我的使用,毕竟满减策略再多也多不到哪去。
我只能说,需求永远不是程序员定的。。这时,市场人员说我们新版程序添加了会员功能,我们需要支持以下的促销策略:
会员促销策略:
会员充300返60,且首单打9折
会员充500返100,且首单打8折
会员充1000返300,且首单打7折
...
这个时候,如果你还在原先的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; } }
好了,现在我们每种策略都有自己独立的空间了,看起来井井有条。但是还有两个问题没有解决:
随着促销策略的增加,
getActualTotal
的代码量依然会越来越大系统缺乏弹性,如果需要增加一种策略,那么除了添加一个策略函数,还需要修改
switch...case..
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
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
本身并没有计算能力,而是将计算全权委托给了策略函数。
由此我们可以总结出策略模式实现的要点:
将变化的算法封装成独立的策略函数,并负责具体的计算
委托函数,该函数接受客户请求,并将请求委托给某一个具体的策略函数
用一张UML图表示如下:
怎么样?现在看到上面这张图是不是有了了然于胸的感觉?那就赶紧去试一试策略模式吧!
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上がデザインパターンの戦略パターンをフロントエンドで使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

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

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Java フレームワークにおけるデザイン パターンとアーキテクチャ パターンの違いは、デザイン パターンがソフトウェア設計における一般的な問題に対する抽象的な解決策を定義し、ファクトリ パターンなどのクラスとオブジェクト間の相互作用に焦点を当てていることです。アーキテクチャ パターンは、階層化アーキテクチャなどのシステム コンポーネントの編成と相互作用に焦点を当てて、システム構造とモジュールの間の関係を定義します。

デコレータ パターンは、元のクラスを変更せずにオブジェクトの機能を動的に追加できる構造設計パターンです。抽象コンポーネント、具象コンポーネント、抽象デコレータ、具象デコレータの連携によって実装され、ニーズの変化に合わせてクラス機能を柔軟に拡張できます。この例では、ミルクとモカのデコレーターが総額 2.29 ドルで Espresso に追加されており、オブジェクトの動作を動的に変更するデコレーター パターンの力を示しています。

デザイン パターンは、再利用可能で拡張可能なソリューションを提供することで、コード メンテナンスの課題を解決します。 オブザーバー パターン: オブジェクトがイベントをサブスクライブし、イベントが発生したときに通知を受信できるようにします。ファクトリ パターン: 具象クラスに依存せずにオブジェクトを作成するための集中的な方法を提供します。シングルトン パターン: クラスには、グローバルにアクセス可能なオブジェクトの作成に使用されるインスタンスが 1 つだけ存在することが保証されます。

Guice フレームワークは、次のような多くの設計パターンを適用します。 シングルトン パターン: @Singleton アノテーションによってクラスのインスタンスが 1 つだけであることを保証します。ファクトリ メソッド パターン: @Provides アノテーションを使用してファクトリ メソッドを作成し、依存関係の注入中にオブジェクト インスタンスを取得します。戦略モード: アルゴリズムをさまざまな戦略クラスにカプセル化し、@Named アノテーションを通じて特定の戦略を指定します。

TDD は、高品質の PHP コードを作成するために使用されます。その手順には、テスト ケースを作成し、期待される機能を記述し、テスト ケースを失敗させることが含まれます。過度な最適化や詳細な設計を行わずに、テスト ケースのみが通過するようにコードを記述します。テスト ケースが合格したら、コードを最適化およびリファクタリングして、可読性、保守性、およびスケーラビリティを向上させます。

アダプター パターンは、互換性のないオブジェクトが連携できるようにする構造設計パターンであり、オブジェクトがスムーズに対話できるように、あるインターフェイスを別のインターフェイスに変換します。オブジェクト アダプタは、適応されたオブジェクトを含むアダプタ オブジェクトを作成し、ターゲット インターフェイスを実装することにより、アダプタ パターンを実装します。実際のケースでは、クライアント (MediaPlayer など) はアダプター モードを通じて高度な形式のメディア (VLC など) を再生できますが、クライアント自体は通常のメディア形式 (MP3 など) のみをサポートします。

Reactの主な機能には、コンポーネント思考、国家管理、仮想DOMが含まれます。 1)コンポーネント化のアイデアにより、UIを再利用可能な部分に分割して、コードの読みやすさと保守性を向上させることができます。 2)状態管理は、状態および小道具を通じて動的データを管理し、変更を変更しますUIの更新をトリガーします。 3)仮想DOM最適化パフォーマンス、メモリ内のDOMレプリカの最小操作の計算を通じてUIを更新します。

SpringMVC フレームワークは次の設計パターンを使用します: 1. シングルトン モード: Spring コンテナーを管理します。 2. ファサード モード: コントローラー、ビュー、およびモデルの対話を調整します。 3. ストラテジ モード: リクエストに基づいてリクエスト ハンドラーを選択します。 : アプリケーション イベントを公開し、リッスンします。これらの設計パターンは SpringMVC の機能と柔軟性を強化し、開発者が効率的で保守可能なアプリケーションを作成できるようにします。
