それはどのように機能し、何に使用され、いつ使用すべきですか?
戦略パターンを簡単な方法で説明しましょう:
クラスCar()
とメソッドrun()
があるため、擬似言語で次のように使用します。
_mycar = new Car()
mycar.run()
_
ここで、プログラムの実行中にrun()
の動作をオンザフライで変更することができます。たとえば、モーターの故障やビデオゲームの「ブースト」ボタンの使用をシミュレートしたい場合があります。
このシミュレーションを行う方法はいくつかあります。条件付きステートメントとフラグ変数を使用することは1つの方法です。戦略パターンは別のものです:run()
メソッドの動作を別のクラスに委任します。
_Class Car()
{
this.motor = new Motor(this)
// passing "this" is important for the motor so it knows what it is running
method run()
{
this.motor.run()
}
method changeMotor(motor)
{
this.motor = motor
}
}
_
車の動作を変更したい場合は、モーターを変更するだけです。 (実際のプログラムよりプログラムの方が簡単ですよね?;-))
複雑な状態が多数ある場合に非常に便利です。状態をより簡単に変更および維持できます。
戦略パターンは、さまざまなstrategiesによって実装または解決される可能性がある(または予測される可能性がある)問題を解決するために使用され、そのような場合に明確に定義されたインターフェースを所有します。各戦略はそれ自体完全に有効であり、実行時にアプリケーションがそれらを切り替えることができる特定の状況では、いくつかの戦略が望ましいです。
namespace StrategyPatterns
{
// Interface definition for a Sort algorithm
public interface ISort
{
void Sort(List<string> list)
}
// QuickSort implementation
public class CQuickSorter : ISort
{
void Sort(List<string> list)
{
// Here will be the actual implementation
}
}
// BubbleSort implementation
public class CBubbleSort : ISort
{
void Sort(List<string> list)
{
// The actual implementation of the sort
}
}
// MergeSort implementation
public class CMergeSort : ISort
{
void Sort(List<string> list)
{
// Again the real implementation comes here
}
}
public class Context
{
private ISort sorter;
public Context(ISort sorter)
{
// We pass to the context the strategy to use
this.sorter = sorter;
}
public ISort Sorter
{
get{return sorter;)
}
}
public class MainClass
{
static void Main()
{
List<string> myList = new List<string>();
myList.Add("Hello world");
myList.Add("Another item");
myList.Add("Item item");
Context cn = new Context(new CQuickSorter());
// Sort using the QuickSort strategy
cn.Sorter.Sort(myList);
myList.Add("This one goes for the mergesort");
cn = new Context(new CMergeSort());
// Sort using the merge sort strategy
cn.Sorter.Sort(myList);
}
}
}
このパターンを使用すると、アプリケーションのすべてまたは一部を再コーディングして再テストする必要がなく、特定の動作を追加または削除することが簡単になります。
良い使い方:
Strategy Pattern Wikipediaの記事から直接 :
戦略パターンは、アプリケーションで使用されるアルゴリズムを動的に交換する必要がある状況で役立ちます。戦略パターンは、アルゴリズムのファミリーを定義し、それぞれをオブジェクトとしてカプセル化し、それらを交換可能にする手段を提供することを目的としています。戦略パターンにより、アルゴリズムを使用するクライアントとは独立してアルゴリズムを変更できます。
密接に関連するパターンはデリゲートパターンです。どちらの場合も、一部の作業は他のコンポーネントに渡されます。私が正しく理解している場合、これらのパターンの違いはこれです(間違っている場合は修正してください)。
Delegateパターンでは、デリゲートは囲んでいる(デリゲートする)クラスによってインスタンス化されます。これにより、継承ではなく構成によるコードの再利用が可能になります。囲んでいるクラスは、デリゲートの具象タイプを認識している場合があります。 (ファクトリを使用するのではなく)コンストラクタ自体を呼び出す場合。
Strategyパターンでは、戦略を実行するコンポーネントは、そのコンストラクターまたはセッター(信仰に従って)を介して、囲んでいる(using)コンポーネントに提供される依存関係です。 usingコンポーネントは、どの戦略が使用されているかをまったく認識していません。戦略は常にインターフェースを介して呼び出されます。
誰か他の違いを知っていますか?
すでに素晴らしい答えに追加するには:戦略パターンは、1つまたは複数の関数を別の関数に渡すことと非常に類似しています。戦略では、これは、関数をオブジェクトでラップした後、オブジェクトを渡すことによって行われます。一部の言語は関数を直接渡すことができるため、パターンをまったく必要としません。しかし、他の言語は関数を渡すことができませんが、 できる オブジェクトを渡す;次にパターンが適用されます。
特にJavaのような言語では、言語のZoo型はかなり小さく、オブジェクトを作成することによって拡張する唯一の方法であることがわかります。したがって、問題のほとんどの解決策はパターンを考え出すことです。特定の目標を達成するためにオブジェクトを構成する方法。型の動物園が豊富な言語では、問題を簡単に解決できる方法が多くありますが、型の種類が多いと、型システムの学習により多くの時間を費やす必要があります。動的タイピングの規律を持つ言語は、問題を巧妙に回避することもよくあります。