web-dev-qa-db-ja.com

戦略パターンV / Sデコレーターパターン

私はちょうど2つのパターンに出くわしました。

  1. 戦略パターン

  2. デコレータ

戦略パターン:-

戦略パターンは、特定の操作またはタスクを実行するために使用できるいくつかのアルゴリズムを提供します。

デコレータパターン:-

デコレータパターンは、コンポーネントにいくつかの機能を追加します。

実際、StrategyパターンとDecoratorパターンも同じように使用できることがわかりました。

リンクは次のとおりです。 デコレータパターンの代わりに、いつどのように戦略パターンを適用できますか?

戦略パターンとデコレーターパターンの違いは何ですか?

戦略パターンを使用する場合とデコレーターパターンを使用する場合

同じ例で両方の違いを説明します。

46
Nirav Kamani

戦略パターンを使用すると、実行時に使用されるものの実装をchangeにできます。

デコレータパターンを使用すると、既存の機能を実行時に追加(または追加)することができます。

主な違いはchange vs augment

あなたがそれにリンクした質問の1つでは、戦略パターンでは消費者は異なるオプションが存在することを認識しているのに対し、デコレーターパターンでは消費者は追加機能を認識しないことを指摘しています。

例として、要素のコレクションをソートするために何かを書いていると想像してください。インターフェイスISortingStrategyを作成すると、いくつかの異なるソート戦略BubbleSortStrategyQuickSortStrategyRadixSortStrategyを実装できます。その後、既存のリストの基準に基づいてアプリケーションが選択しますリストのソートに使用する最も適切な戦略。たとえば、リストに含まれるアイテムが10個未満の場合はRadixSortStrategyを使用し、最後の並べ替え以降にリストに追加されたアイテムが10個未満の場合はBubbleSortStrategyを使用し、そうでない場合はQuickSortStrategy

実行時にソートのタイプを変更しています(追加情報に基づいてより効率的にするため)。これが戦略パターンです。

次に、実際のソートを行うために各ソートアルゴリズムが使用される頻度のログを提供し、ソートを管理ユーザーに制限するように誰かに依頼されたとします。 anyISortingStrategyを拡張するデコレーターを作成することにより、これらの機能の両方を追加できます。何かのソートに使用されたことをログに記録するデコレータと、装飾されたソート戦略のタイプを作成できます。また、装飾された並べ替え方法を呼び出す前に、現在のユーザーが管理者であるかどうかを確認する別のデコレータを追加できます。

ここでは、デコレータを使用して任意の並べ替え戦略に新しい機能を追加していますが、コアの並べ替え機能は交換していません(異なる戦略を使用して変更しました)

デコレータの外観の例を次に示します。

public interface ISortingStrategy
{
    void Sort(IList<int> listToSort);
}

public class LoggingDecorator : ISortingStrategy
{
    private ISortingStrategy decorated;
    public LoggingDecorator(ISortingStrategy decorated)
    {
         this.decorated=decorated;
    }

    void Sort(IList<int> listToSort)
    { 
         Log("sorting using the strategy: " + decorated.ToString();
         decorated.Sort(listToSort);
    }
}

public class AuthorisingDecorator : ISortingStrategy
{
    private ISortingStrategy decorated;
    public AuthorisingDecorator(ISortingStrategy decorated)
    {
         this.decorated=decorated;
    }

    void Sort(IList<int> listToSort)
    { 
         if (CurrentUserIsAdministrator())
         {
             decorated.Sort(listToSort);
         }
         else
         {
             throw new UserNotAuthorizedException("Only administrators are allowed to sort");
         }
    }
}
87
Sam Holder

Strategy_pattern

  1. アルゴリズムのファミリーを定義し、
  2. 各アルゴリズムをカプセル化し、
  3. そのファミリ内でアルゴリズムを交換可能にします。

実行時にアルゴリズムを動的に変更する必要がある場合は、戦略パターンを使用します。

デコレーター

Decoratorパターンは、オブジェクトの既存の機能に影響を与えることなく、実行時にオブジェクトの機能を動的に変更します。

使用する場合:

  1. 追加の機能/責任を動的に追加する
  2. 機能/責任を動的に削除する
  3. 追加の責任を追加するために、サブクラス化をあまり避けてください。

欠点:

  1. オープンクローズの原則の過剰使用(拡張のためにオープン、変更のためにクローズ)。コードが変更される可能性が最も低い場所では、この機能を控えめに使用してください。
  2. 少人数のクラスが多すぎるため、メンテナンスのオーバーヘッドが追加されます。

鍵の違い:

Strategyでは、オブジェクトの内臓を変更できます。デコレータを使用すると、スキンを変更できます。

その他の便利な投稿:

デコレータパターンを使用する場合

戦略パターンの実世界の例

戦略 ソースメイキングによる

9
Ravindra babu

この戦略は、「変更内容をカプセル化する」ために使用されるパターンです。実行時に交換できるアルゴリズムを定義できます。例(Head First Design Patternsからの例):

アヒルシミュレーターがあるとします。アヒルのオブジェクトを飛ばせます。これには継承を使用できますが、すぐに面倒になります。一部のアヒルは飛べません(ゴム製のアヒルなど)。これを行う方法は、何が変わるか、つまり、フライの動作を、たとえばIFlybehaviourを実装する独自のクラスにカプセル化することです。その後、継承の代わりにコンポジションを使用して、ダックオブジェクトにIFlybehaviourを注入できます。実行時にフライの動作を変更できるように、このフライの動作を設定するメソッドを用意することもできます。これは基本的に戦略パターンです。

デコレータパターンは、実行時にオブジェクトに機能を追加するために使用されます。オブジェクト内でオブジェクトをラップできます。デコレータには、装飾するオブジェクトと同じスーパータイプが必要です。これにより、「最も外側のラッパー」でメソッドを呼び出すことができ、デコレーターのレイヤーを通してこの同じメソッドをチェーン呼び出しできます。基本的に、サブクラス化よりも柔軟なアプローチです。

どれを選択するかは、解決したい問題によって異なります。実行時に交換可能なアルゴリズムのファミリーが必要ですか、それとも実行時にオブジェクトに機能を動的に追加しますか?

「ヘッドファーストデザインパターン」という本は、これを非常によく説明しているので(おそらく私よりもはるかに優れています)IMOなので、チャンスがあれば読む価値があります。

幸運を。

5
Magrangs

戦略はアルゴリズムを選択しています。

Collections.sort(list, comparator); // comparator is the strategy

デコレータは、同じタイプを維持しながらオブジェクトをラップしています。

in = new BufferedInputStream(in);
1
Mark Jeronimus

つまり、戦略を使用して、コア機能の1つを選択します。デコレータを使用して、追加機能を追加します。戦略は私たちが作っているケーキであり、デコレーターは私たちがそれに追加するすべてのきれいな装飾です。

1
kirk.burleson

デコレータは、クラスのインスタンスに追加機能を追加するため、ランタイムに動的に実装されます。これは、動作拡張のパターンです。サブクラス化が逆行する実用的な条件のため。ストラテジーは、異なるストラテジーオブジェクトが同じ抽象機能を共有するパターンです。具体的なコンテキストオブジェクトは、実行時にファミリセットの具体的なストラテジーオブジェクトで構成できます。 MVCのように、コントローラーは戦略的役割のケースであり、ビューは出力データ構造を制限しますが、コントローラーは実行時に異なるため、ビューの出力データを動的に変更します。

0
YoungJeXu