戦略デザインパターンと状態デザインパターンの違いは何ですか?


219

戦略デザインパターンと州デザインパターンの違いは何ですか?私はウェブ上でかなりの数の記事を調べていましたが、違いを明確に理解することができませんでした。

誰かが素人の言葉の違いを説明できますか?


ここでの回答と私自身の観察に基づいて、実装はほとんど(完全ではないが)同じであるようです。むしろ、違いは主に意図の1つです。つまり、状態(状態パターン)または他の何か(戦略パターン)に基づいて動作を適応させようとしています。注入を通じて、別の何かが「クライアントが選択するもの」であることがよくあります。
Timo

回答:


139

正直なところ、2つのパターンは実際にはかなり似ており、それらの間の明確な違いは、質問する人によって異なる傾向があります。一般的な選択肢は次のとおりです。

  • 状態には、状態を含むコンテキストオブジェクトへの参照が格納されます。戦略にはありません。
  • 状態はそれ自体を置き換えることができます(IE:コンテキストオブジェクトの状態を別のものに変更するため)。一方、戦略はそうではありません。
  • 戦略はパラメータとしてコンテキストオブジェクトに渡されますが、状態はコンテキストオブジェクト自体によって作成されます。
  • 戦略は単一の特定のタスクのみを処理しますが、状態はコンテキストオブジェクトが行うすべて(またはほとんどすべて)の基本的な実装を提供します。

「クラシック」な実装は、リストのすべての項目の状態または戦略のいずれかに一致しますが、両方が混在するハイブリッドにまたがって実行します。特定のものがより国家的であるか戦略的であるかは最終的に主観的な質問です。


6
GoFを人気のある選択肢の1つとして数えている場合、状態は必ずしもコンテキストによって作成される(クライアントが作成して、ストラテジーと同様にコンテキストに渡すことができる)ことに同意しません。
ウィルハードウィックスミス

109
  • 戦略パターンは戦略が必要となるように、1つの実装は、他に置き換えることができるように、(基本的に)実現異なる実装を持っていることについて、本当に同じものです。たとえば、戦略パターンに異なるソートアルゴリズムがある場合があります。オブジェクトの呼び出し元は、採用されている戦略に基づいて変化しませんが、戦略に関係なく、目標は同じです(コレクションを並べ替えます)。
  • 国家のパターンは、すべての可能な状態を収容する負担から解放発信者を残したまま、状態に基づいて異なることをやってについてです。したがって、たとえばgetStatus()、オブジェクトの状態に基づいて異なるステータスを返すメソッドがある場合でも、 メソッドの呼び出し元を、それぞれの潜在的な状態に対応するために別の方法でコーディングする必要はありません。

1
しかし、戦略パターンで戦略を変更するのは誰ですか?
Noor

1
@Noor、通常は何らかのパラメータまたはフィールドです。実際の呼び出し元のコードは、戦略の変更に基づいて変更されることはありません。
Yishai

4
@Noor、はい、しかし私が今考えることができるどんな戦略パターンでも、それは途中で変わらない前払いの決定です。
Yishai 2013年

2
私は同じ問題を抱えていますが、状態または戦略ですが、いくつかの言葉の違いは、状態、行動は自動決定、戦略、行動は呼び出し元によって決定されると思います。
ルネMF

1
eコマースアプリケーションでは、追加の割引をお祝いシーズンに適用する必要がある場合、それは状態デザインパターンです。その数に到達する方法が複数ある場合は、実際の割引率ロジックを戦略設計パターンに適用できます。
Bharathkumar V

85

違いは、それらが異なる問題を解決するということです。

  • 状態のパターンディールどのオブジェクトが(中)である(状態またはタイプ) -それは一方で、状態依存挙動をカプセル化
  • 戦略とパターンディールどのようにオブジェクトが特定のタスクを実行するには-それは、アルゴリズムをカプセル化します。

ただし、これらの異なる目標を達成するための構成は非常に似ています。どちらのパターンも、委任による構成の例です。


それらの利点に関するいくつかの観察:

使用して状態パターンを状態保持(コンテキスト)クラスの知識から解放されるものがある状態またはタイプとどのように入手可能である状態またはタイプ。これは、クラスが開閉式設計原則(OCP)に準拠していることを意味します。クラスは、どのような状態/タイプがあるかを変更するために閉じられますが、状態/タイプは拡張に対して開かれています。

Strategyパターンを使用することにより、アルゴリズムを使用する(コンテキスト)クラスは、特定のタスク(-「アルゴリズム」)を実行する方法の知識から解放されます。このケースは、OCPへの準拠も作成します。このタスクを実行する方法に関する変更のためにクラスはクローズされていますが、このタスクを解決するための他のアルゴリズムの追加に対して設計は非常にオープンです。
これにより、コンテキストクラスの単一責任原則(SRP)への準拠も改善される可能性があります。さらに、アルゴリズムは他のクラスによる再利用が容易になります。


42

誰かが素人の言葉で説明してくれませんか?

デザインパターンは実際には「素人」の概念ではありませんが、できるだけ明確にするようにします。設計パターンは3次元で検討できます。

  1. パターンが解決する問題。
  2. パターンの静的構造(クラス図)。
  3. パターンのダイナミクス(シーケンス図)。

状態と戦略を比較してみましょう。

パターンが解決する問題

状態は2つのケースのいずれかで使用されます[GoF book p。306]

  • オブジェクトの動作はその状態に依存し、その状態に応じて実行時にオブジェクトの動作を変更する必要があります。
  • 操作には、オブジェクトの状態に依存する大きなマルチパート条件ステートメントがあります。この状態は通常、1つ以上の列挙定数で表されます。多くの場合、いくつかの操作にはこの同じ条件構造が含まれます。Stateパターンは、条件の各ブランチを個別のクラスに配置します。これにより、オブジェクトの状態を、他のオブジェクトとは独立して変化することができるそれ自体がオブジェクトとして扱うことができます。

Stateパターンが実際に解決する問題があることを確認したい場合は、有限状態マシンを使用してオブジェクトの状態をモデル化できるはずです。ここに適用例があります

各状態遷移は、Stateインターフェースのメソッドです。これは、設計では、このパターンを適用する前に、状態遷移についてかなり確実にする必要があることを意味します。それ以外の場合、遷移を追加または削除すると、インターフェースとそれを実装するすべてのクラスを変更する必要があります。

私は個人的にはこのパターンが有用だとは思いませんでした。ルックアップテーブルを使用して有限状態機械をいつでも実装できます(オブジェクト指向の方法ではありませんが、かなりうまくいきます)。

戦略は、次の[GoFブックp。316]

  • 関連するクラスの多くは、動作のみが異なります。戦略は、多くの動作の1つでクラスを構成する方法を提供します。
  • アルゴリズムのさまざまなバリアントが必要です。たとえば、異なる空間/時間のトレードオフを反映するアルゴリズムを定義できます。これらのバリアントがアルゴリズムのクラス階層として実装されている場合、戦略を使用できます[HO87]。
  • アルゴリズムは、クライアントが知らないはずのデータを使用します。Strategyパターンを使用して、複雑なアルゴリズム固有のデータ構造を公開しないようにします。
  • クラスは多くの動作を定義し、それらはその操作で複数の条件ステートメントとして表示されます。多くの条件文の代わりに、関連する条件分岐を独自の戦略クラスに移動します。

ストラテジーを適用する最後のケースは、「条件付きのポリモーフィズムへの置き換え」として知られるリファクタリングに関連しています。

概要:国家と戦略は非常に異なる問題を解決します。問題を有限状態機械でモデル化できない場合、おそらく状態パターンは適切ではありません。問題が複雑なアルゴリズムのバリアントのカプセル化に関するものではない場合、戦略は適用されません。

パターンの静的構造

状態には、次のUMLクラス構造があります。

状態パターンのPlantUMLクラス図

Strategyの UMLクラス構造は次のとおりです。

戦略パターンのPlantUMLクラス図

要約:静的構造の点では、これら2つのパターンはほとんど同じです。実際には、のようなパターン検出ツールこれは「と考えるの構造は、[...]パターン(例えば、概念的な情報を参照することなく)自動プロセスによって、それらの区別を禁止する、同じです。

ただし、ConcreteStatesが状態遷移を自分で決定する場合は、大きな違いが生じる可能性があります(上の図の「かもしれない」の関連付けを参照してください)。これにより、具象状態が結合されます。たとえば(次のセクションを参照)、状態Aは状態Bへの遷移を決定します。Contextクラスが次の具象状態への遷移を決定すると、これらの依存関係はなくなります。

パターンのダイナミクス

上記の問題のセクションで述べたように、国家は、実行時の動作の変更がいくつかに依存することを意味状態オブジェクトの。したがって、有限状態マシンの関係で説明したように、状態遷移の概念が適用されます。[GoF]は、遷移は、ConcreteStateサブクラスまたは集中型の場所(テーブルベースの場所など)で定義できると述べています。

単純な有限状態機械を想定しましょう:

2つの状態と1つの遷移を持つPlantUML状態遷移図

サブクラスが状態遷移を決定すると(次の状態オブジェクトを返すことにより)、ダイナミックは次のようになります。

状態遷移のPlantUMLシーケンス図

Strategyのダイナミクスを示すには、実際の例を借用すると便利です。

戦略遷移のPlantUMLシーケンス図

概要:各パターンは、ポリモーフィックコールを使用して、コンテキストに応じて何かを行います。状態パターンでは、ポリモーフィックな呼び出し(遷移)により、次の状態に変化が生じることがよくあります。Strategyパターンでは、通常、ポリモーフィックな呼び出しはコンテキストを変更しません(たとえば、一度クレジットカードで支払うことは、次回PayPalで支払うことを意味しません)。繰り返しますが、状態パターンのダイナミクスは、対応するfininteステートマシンによって決定されます。


この回答は、違いを区別するのに非常に役立ちました。ステートマシンの議論は適切な私見であるように思えます。これは実際に、上記の答えを理論的なコンピューターサイエンスの方法で要約したものです。
メデューン

この答えは非常に役立ちます。私にとってはこれが一番です。
Chofoteddy

25

戦略パターンでは、アルゴリズムの実装をホスティングクラスから移動し、別のクラスに配置します。これは、ホストクラスが各アルゴリズム自体の実装を提供する必要がないことを意味します。これは、不明瞭なコードにつながる可能性があります。

並べ替えアルゴリズムは、すべて同じ種類の処理(並べ替え)を行うため、通常は例として使用されます。異なる並べ替えアルゴリズムをそれぞれ独自のクラスに配置すると、クライアントは使用するアルゴリズムを簡単に選択でき、パターンはそれにアクセスする簡単な方法を提供します。

状態パターンには、オブジェクトの状態が変化したときにオブジェクトの動作を変更することが含まれます。これは、ホストクラスが、すべての異なる状態の動作の実装を提供していないことを意味します。ホストクラスは通常、特定の状態で必要な機能を提供するクラスをカプセル化し、別のクラスに切り替えます状態が変化したとき。


16

カスタマーコールを処理するIVR(インタラクティブボイスレスポンス)システムを検討してください。次の顧客を処理するようにプログラムすることができます。

  • 就業日
  • 祝日

この状況を処理するには、状態パターンを使用できます。

  • 休日:IVRは、「電話は午前9時から午後5時までの営業日にしか受けられない」と応答します。
  • 稼働日:カスタマーケアエグゼクティブに顧客をつなぐことで対応します。

顧客をサポートエグゼクティブに接続するこのプロセス自体は、次のいずれかに基づいてエグゼクティブが選ばれる戦略パターンを使用して実装できます。

  • ラウンドロビン
  • 最近使用されていない
  • その他の優先度ベースのアルゴリズム

戦略パターンは「どのように」アクションを実行するかを決定し、状態パターンは「いつ」アクションを実行するかを決定します。


これは優れた答えであり、過小評価されています。しかし、あなたの例でなぜ多くのアルゴリズムが必要なのか言及することは役に立ちます。たとえば、アルゴリズムはコールセンター会社の好みに基づいて選択されます。また、RRまたはLRUを知らない人のために、リストに単純なアルゴリズムまたは自明なアルゴリズムがある場合にも役立ちます。例-長い時間顧客の優先度が高くなり、最も待った顧客の優先度が高くなります。よろしくお願いします!
MasterJoe2

14

戦略は、何かを「実行」するオブジェクトを表します。開始結果と終了結果は同じですが、内部的には異なる方法論を使用しています。その意味で、それらは動詞の実装を表すことに類似しています。状態パターンOTOHは、何かであるオブジェクト、つまり操作の状態を使用します。それらはそのデータの操作も表すことができますが、動詞よりも名詞の表現により類似しており、状態機械に合わせて調整されています。


11

戦略:戦略は固定されており、通常はいくつかのステップで構成されます。(ソートは1つのステップのみを構成するため、このパターンの目的を理解するには原始的すぎるため、非常に悪い例です)。戦略の「メイン」ルーチンがいくつかの抽象メソッドを呼び出しています。たとえば、「Enter Room Strategy」、「main-method」はgoThroughDoor()で、次のようになります。openDoor(); enterRoom(); 順番(); closeDoor(); if(wasLocked())lockDoor();

ロックされている可能性のあるドアを介して1つの部屋から別の部屋に移動するためのこの一般的な「アルゴリズム」のサブクラスは、アルゴリズムのステップを実装できます。

つまり、戦略をサブクラス化しても基本的なアルゴリズムは変更されず、個々のステップのみが変更されます。

上記はテンプレートメソッドパターンです。次に、一緒に属するステップ(ロック解除/ロックおよびオープン/クローズ)を独自の実装オブジェクトに入れ、それらに委任します。たとえば、キー付きロックとコードカード付きロックは2種類のロックです。戦略から「ステップ」オブジェクトに委任します。これで戦略パターンが完成しました。

状態パターンは完全に異なるものです。

あなたはラッピングオブジェクトとラップされたオブジェクトを持っています。包まれたものが「状態」です。状態オブジェクトは、そのラッパーを介してのみアクセスされます。これで、いつでもラップされたオブジェクトを変更できるため、ラッパーはその状態、または「クラス」やタイプさえも変更しているように見えます。

たとえば、ログオンサービスがあるとします。ユーザー名とパスワードを受け入れます。logon(String userName、String passwdHash)という1つのメソッドしかありません。ログオンを受け入れるかどうかを自分で決定する代わりに、状態オブジェクトに決定を委任します。その状態オブジェクトは通常、ユーザーとパスの組み合わせが有効かどうかを確認し、ログオンを実行します。しかし、今では、「チェッカー」を、特権ユーザーのみがログオンできるようにする(メインテナンス時など)か、誰もログオンできないようにすることで交換できます。これは、「チェッカー」がシステムの「ログオン状態」を表すことを意味します。

最も重要な違いは次のとおりです。戦略を選択したときは、それが終わるまでそれを堅持します。つまり、その「メインメソッド」を呼び出し、そのメソッドが実行されている限り、戦略を変更することはありません。OTOHは、システムの実行時の状態パターンの状況で、状況に応じて任意に状態を変更します。


9

戦略パターンは、特定のタスクに複数のアルゴリズムがあり、クライアントが実行時に使用する実際の実装を決定する場合に使用されます。

Wikiの戦略パターン記事のUML図:

ここに画像の説明を入力してください

主な機能:

  1. それは行動パターンです。
  2. 委任に基づいています。
  3. メソッドの振る舞いを変更することにより、オブジェクトの根性を変更します。
  4. これは、アルゴリズムのファミリーを切り替えるために使用されます。
  5. 実行時にオブジェクトの動作を変更します。

詳細と実際の例については、この投稿を参照してください。

戦略パターンの実例

状態パターンにより、内部状態が変化したときにオブジェクトの動作を変更できます

ウィキの状態パターン記事からのUML図 :

ここに画像の説明を入力してください

オブジェクトの状態に基づいてオブジェクトの動作を変更する必要がある場合は、オブジェクトに状態変数を設定し、if-else条件ブロックを使用して、状態に基づいてさまざまなアクションを実行できます。状態パターンは、コンテキスト状態の実装を通じてこれを達成するための体系的で結合された方法を提供するために使用されます。

詳細については、このjournaldevの記事を参照してください。

ソースメイキングjournaldevの記事との主な違い:

  1. 国家戦略の違いは拘束時間にあります。戦略はバインドワンスパターンですが、状態はより動的です。
  2. 国家戦略の違いは意図にあります。Strategyでは、アルゴリズムの選択はかなり安定しています。状態では、「コンテキスト」オブジェクトの状態が変化すると、ストラテジオブジェクトの「パレット」から選択されます
  3. コンテキストにはインスタンス変数として状態が含まれ、その実装が状態に依存する可能性のある複数のタスクが存在する可能性がありますが、戦略パターンでは戦略がメソッドの引数として渡され、コンテキストオブジェクトにはそれを格納する変数がありません。

5

素人の言葉で

戦略パターンでは、状態がないか、すべてが同じ状態です。異なる医師が同じ状態の同じ患者の同じ病気を異なる方法で治療するように、すべての人がタスクを実行する異なる方法です。

状態パターンでは、主観的に、患者の現在の状態(高温または低温など)のような状態があり、それに基づいて次の行動方針(薬の処方)が決定されます。また、ある状態が別の状態につながる可能性があるため、状態があります。依存関係(技術的には構成)を述べる。

両者のコード比較に基づいて技術的に理解しようとすると、両方が非常に似ているため、状況の主観性を失う可能性があります。


2

どちらのパターンもいくつかの派生クラスを持つ基本クラスに委譲しますが、これらの派生クラスがコンテキストクラスへの参照を保持するのはStateパターン内だけです。

別の見方をすると、戦略パターンは状態パターンのより単純なバージョンです。必要に応じて、サブパターン。派生した状態で参照をコンテキストに戻すかどうか(つまり、コンテキストでメソッドを呼び出すかどうか)は、実際に依存します。

詳細については、Robert C Martin(およびMicah Martin)が彼らの著書「C#でのアジャイル原則、パターン、および実践」でこれに答えています。(http://www.amazon.com/Agile-Principles-Patterns-Practices-C/dp/0131857258


2

これはかなり古い質問ですが、それでも私は同じ答えを探していましたが、これは私が発見したものです。

状態パターンについて、内側のプレーヤーの再生ボタンの例を考えてみましょう。再生すると、再生が開始され、再生中であることがコンテキストに認識されます。クライアントは再生操作を実行するたびに、プレーヤーの現在の状態を確認します。これでクライアントは、オブジェクトの状態がコンテキストオブジェクトを介して再生されていることを認識できるため、状態オブジェクトの一時停止アクションメソッドを呼び出します。クライアントの状態を認識し、アクションを実行するために必要な状態を自動化できます。

https://www.youtube.com/watch?v=e45RMc76884 https://www.tutorialspoint.com/design_pattern/state_pattern.htm

戦略パターンの場合、クラス図の配置は状態パターンと同じです。クライアントは、いくつかの操作を行うためにこの配置になります。つまり、さまざまな状態の代わりに、たとえば、パターンに対して実行する必要があるさまざまな分析など、さまざまなアルゴリズムがあります。ここでクライアントは、何をしたいのか、どのアルゴリズム(ビジネス定義のカスタムアルゴリズム)を実行するかをコンテキストに伝え、それを実行します。

https://www.tutorialspoint.com/design_pattern/strategy_pattern.htm

どちらもオープンクローズの原則を実装しているため、開発者は状態パターンと新しいアルゴリズムに新しい状態を追加できます。

しかし、違いは、オブジェクトの状態に基づいてさまざまなロジックを実行するために使用される状態パターンである、それらが使用されるものです。そして戦略のケースでは異なるロジック。


2

状態には、状態の派生クラス内に少し依存関係があります。ある状態は、その後に続く他の状態について知っているようです。たとえば、夏はあらゆるシーズンの状態で冬の後に来ます。また、ショッピングのデポジット状態の後に配達状態になります。

一方、Strategyには、このような依存関係はありません。ここでは、プログラム/製品タイプに基づいて、あらゆる種類の状態を初期化できます。


1

違いはhttp://c2.com/cgi/wiki?StrategyPatternで説明されています。データ分析の全体的なフレームワーク内でさまざまなアルゴリズムを選択できるようにするために、Strategyパターンを使用しました。これにより、フレームワーク全体とそのロジックを変更せずにアルゴリズムを追加できます。

典型的な例は、あなたが関数を最適化するためのフレームワークを持っていることです。フレームワークはデータとパラメータを設定します。戦略パターンでは、フレームワークを変更せずに、sttepest descents、共役勾配法、BFGSなどのアルゴリズムを選択できます。


1

戦略パターンと状態パターンはどちらも同じ構造です。両方のパターンのUMLクラス図を見ると、それらはまったく同じに見えますが、意図はまったく異なります。状態設計パターンはオブジェクトの状態を定義および管理するために使用され、戦略パターンは交換可能なアルゴリズムのセットを定義するために使用され、クライアントがそれらの1つを選択できるようにします。したがって、ストラテジーパターンはクライアント主導のパターンであり、オブジェクトはステート自体を管理できます。


1

つまり、戦略パターンを使用すると、動作をその場で設定できます。状態パターンを使用すると、オブジェクトの状態が変化すると、オブジェクトの動作が内部的に変化することを確認できます。


0

2つのタスクに分割できるプロジェクトがある場合:

タスク1:次の2つのアルゴリズムのいずれかを使用して実行できます:alg1、alg2

タスク2:3つの異なるアルゴリズムのいずれかを使用して、alg3、alg4、alg5を実行できます。

alg1とalg2は交換可能です。alg3、alg4、alg5は交換可能です。

タスク1とタスク2で実行するアルゴリズムの選択は、状態によって異なります。

状態1:タスク1にalg1、タスク2にalg3が必要

状態2:タスク1にalg2、タスク2にalg5が必要

コンテキストにより、状態オブジェクトを状態1から状態2に変更できます。その後、alg1とalg3ではなく、alg2とalg5によってタスクが実行されます。

タスク1またはタスク2にはさらに互換性のあるアルゴリズムを追加できます。これは戦略パターンです。

タスク1とタスク2では、アルゴリズムの異なる組み合わせでより多くの状態を設定できます。状態パターンを使用すると、ある状態から別の状態に切り替えて、アルゴリズムの異なる組み合わせを実行できます。


0

「戦略」は、必要に応じてさまざまな状況で変更できるアルゴリズムにすぎず、何かを処理します。例 ファイルの圧縮方法を選択できます。メソッドのzipまたはrar ...

しかし、「状態」は、オブジェクトのすべての動作を変更できます。変更すると、他のフィールドを変更することもできます...そのため、所有者への参照があります。オブジェクトフィールドを変更すると、オブジェクトの動作がまったく変わる可能性があることに注意してください。例 objでState0をState1に変更すると、整数が10に変更されます。そのため、何らかの計算を行ってその整数を使用するobj.f0()を呼び出すと、結果に影響します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.