変更された戦略設計パターン


11

私は最近、デザインパターンの調査を開始しましたが、コーディングしていることの1つは、小さな違いを除いて、戦略パターンに完全に適合します。

基本的に、私のアルゴリズムの一部(すべてではない)には、追加のパラメーターまたは2つを渡す必要があります。

だから私はどちらかをする必要があります

  • 計算メソッドを呼び出すときに追加のパラメーターを渡します

または

  • それらをConcreteAlgorithmクラス内の変数として保存し、アルゴリズムを呼び出す前にそれらを更新できるようにします。

このニーズに合ったデザインパターンはありますか/戦略パターンにこだわってこれを実装するにはどうすればよいですか?

クライアントオブジェクトをすべてのアルゴリズムに渡し、変数をそこに格納し、特定のアルゴリズムで必要な場合にのみ使用することを検討しました。しかし、これは扱いにくく、戦略パターンのポイントを打ち負かすと思います。

明確にするために、私はJavaで実装しているので、オプションのパラメーター(これをうまく解決できる)の贅沢はありません。


C ++のようなオプションのパラメーターは、複数のオーバーロードメソッドを定義するための単なる省略形であるため、何も解決しません。
-maaartinus

追加のパラメーターを使用前に変更する必要がある場所に保存しないように努めます。このようにして、ConcreteAlgorithmをステートフルにするため、他のメソッドやスレッドに簡単に渡すことはできません。さらに、パラメーターの設定を忘れるのも簡単です。
-maaartinus

回答:


5

サミュエル、各戦略が1つの共通クラスに取り入れるパラメーターをカプセル化してから、その共通パラメータークラスを拡張して、戦略の一部が特に必要とする動作を追加することは可能ですか?

例えば

StrategyParameter //Base strategy parameter that most of the strategies need
        ^
        |
        |
SpecialStrategyParameter // will be used for strategies that need more parameter

次に、次のような戦略階層を定義します。

Interface MyStrategy {
   void myStrategyMethod(StrategyParameter parameter);
}

class MyNormalStrategy extends MyStrategy {
   void myStrategyMethod(StrategyParameter parameter) {
       //implement the logic here
   }
}

上記の戦略を次のように呼び出します。 myNormalStrategyInstance.myStrategyMethod(strategyParameter);

class MySpecializedStrategy extends MyStrategy {
   void myStrategyMethod(StrategyParameter parameter) {
       //implement the logic here
   }
}

SpecialStrategyParameter代わりに次のようにインスタンスを渡すことにより、上記の戦略を呼び出します。mySpecializedStrategy.myStrategyMethod(specialStrategyParameter);

不明な点がある場合は更新してください。説明/明確に説明させていただきます。


1
-1はダウンキャストを必要とし、設計のカプセル化を中断します。それは問題のデザインの改善ですが、この猫の皮を剥ぐより良い方法があります。
-tallseth

@tallsethダウンキャストも見ます。しかし、私はより良い方法を見ていません。より良い解決策を指摘していただけますか?記事か何か?
ナレク

実はそうです。@Jordãoには、質問の詳細に基づいて、私が好む答えがあります。その答えは、戦略パターンの長所になります。この回答でアプローチを行った場合StrategyParameter、すべての可能なパラメーターをDTOとして含める必要があります。戦略のいくつかの実装はそれらを無視できます。場合によっては、それが最善のアプローチです。コンテキストは、これらの種類の問題の王です。
-tallseth

3

戦略を明確にする必要があります。

それはすべて、アルゴリズムの使用方法によって異なります。クライアントクラスが異なる戦略実装を交換可能に使用するには、すべてのクラスで共通の抽象化が必要です。それらが同じインターフェースに従っていない場合、必要なのは異なる抽象化でしょう。

前に構成可能な戦略を使用しました。ここでは、構築時に具体的なクラスをパラメーター化します。

interface Strategy {
  int calculate();
}

class ConcreteStrategyThatNeedsAParameter implements Strategy {
  private final int param;
  public ConcreteStrategyThatNeedsAParameter(int param) {
    this.param = param;
  }
  public int calculate() { 
    // uses param...
  }
}

今、誰かがこのクラスのインスタンスを作成してクライアントに渡す必要があります。ただし、クライアントはStrategyインターフェースについて知るだけで十分です。

戦略メソッドがパラメーターを取得する場合も機能しますが、クライアントはそれらのパラメーターを認識し、動作するすべての実装にそれらを渡します。


クライアントは、パラメーターを提供するコンテキストを持つクライアントです。
-andyczerwonka

1

署名がインターフェースで明確に定義されている限り、それはまだ戦略パターンに準拠しています。

記述されたパターンは、予想される動作を示す絶対的な最も単純な形式であるため、元の意図を維持する限り、装飾することができます。もちろん、パターンに従うことを前提としています。パターンが収まらない場合、またはパターンが存在するという理由だけでパターンを使用しても意味がありませんが、あなたの場合は大丈夫だと思います。


0

peakitが提供する上記の答えを拡張します-抽象化を使用できます。ここでpeakitのコードを使用しています-

インターフェイスMyStrategy { abstract void myStrategyMethod(StrategyParameter parameter); }

class MyNormalStrategy extends MyStrategy {public override void myStrategyMethod(StrategyParameter parameter){//ここにロジックを実装します}}

クラスMySpecializedStrategyはMyStrategyを拡張します{public override void myStrategyMethod(StrategyParameter parameter、ExtraStrategyParameter extraParameter){//ここにロジックを実装します} }

あなたの質問を正しく理解したら、追加のパラメータを特定のアルゴリズムに渡したいですか?これがあなたが探していたものかどうか教えてください?


0

設計パターンの本を見ると、渡されたパラメーターをほとんどまたはまったく使用しないSimpleStrategyが存在すること、またはパラメーターが1サイズにすべて適合/最小共通乗数であること自体は間違っていません。ここでの設計上の選択は、使用されない追加の処理に関してこれがあなたを傷つけるかどうかです。

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