それはどのように機能し、何のために使用され、いつ使用すべきですか?
6 に答える
戦略パターンを簡単な方法で説明しましょう。
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
}
}
車の動作を変更したい場合は、モーターを変更するだけです。(プログラムでは実際よりも簡単ですよね?;-))
複雑な状態がたくさんある場合に非常に便利です。それらをはるかに簡単に変更および保守できます。
問題
戦略パターンは、さまざまな戦略によって実装または解決される可能性がある (または予測される) 問題を解決するために使用され、そのような場合に明確に定義されたインターフェースを備えています。各戦略はそれ自体で完全に有効であり、アプリケーションが実行時にそれらを切り替えることができる特定の状況では、いくつかの戦略が望ましいです。
コード例
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);
}
}
}
- 戦略とは?戦略とは、特定の目標を達成するために設計された行動計画です。
- 「アルゴリズムのファミリーを定義し、それぞれをカプセル化し、交換可能にします。戦略により、アルゴリズムは、それを使用するクライアントとは独立して変更できます。」(ギャング・オブ・フォー);
- それぞれが潜在的な動作を表す一連のクラスを指定します。これらのクラスを切り替えると、アプリケーションの動作が変わります。(戦略);
- この動作は、実行時 (ポリモーフィズムを使用) または設計時に選択できます。
- インターフェイスで抽象化をキャプチャし、実装の詳細を派生クラスに埋め込みます。
- ストラテジーに代わる方法は、条件付きロジックを使用してアプリケーションの動作を変更することです。(悪い);
このパターンを使用すると、アプリケーションのすべてまたは一部を再コーディングおよび再テストすることなく、特定の動作を追加または削除することが容易になります。
良い用途:
- 同様のアルゴリズムのセットがあり、アプリケーションのさまざまな部分でそれらを切り替える必要がある場合。戦略パターンを使用すると、ifs を回避し、メンテナンスを容易にすることができます。
- すべてのサブクラスにとって必ずしも意味をなさない新しいメソッドをスーパークラスに追加したい場合。新しいメソッドを追加する従来の方法でインターフェースを使用する代わりに、新しい Functionality インターフェースのサブクラスであるインスタンス変数を使用します。これは合成と呼ばれます。継承によって能力を継承する代わりに、クラスは適切な能力を持つオブジェクトで構成されます。
密接に関連するパターンは、委任パターンです。どちらの場合も、作業の一部は他のコンポーネントに渡されます。私が正しく理解していれば、これらのパターンの違いは次のとおりです(間違っている場合は訂正してください)。
デリゲートパターンでは、デリゲートは囲んでいる(委任している)クラスによってインスタンス化されます。これにより、継承ではなく構成によるコードの再利用が可能になります。囲んでいるクラスは、デリゲートの具象型を認識している場合があります。たとえば、(ファクトリを使用するのではなく)コンストラクタ自体を呼び出す場合です。
ストラテジーパターンでは、ストラテジーを実行するコンポーネントは、コンストラクターまたはセッター(宗教に応じて)を介して囲んでいる(使用している)コンポーネントに提供される依存関係です。使用しているコンポーネントは、どの戦略が使用されているかをまったく認識していません。戦略は常にインターフェースを介して呼び出されます。
誰か他の違いを知っていますか?
ストラテジーパターンウィキペディアの記事から直接:
戦略パターンは、アプリケーションで使用されるアルゴリズムを動的に交換する必要がある状況で役立ちます。戦略パターンは、アルゴリズムのファミリーを定義し、それぞれをオブジェクトとしてカプセル化し、それらを交換可能にする手段を提供することを目的としています。戦略パターンにより、アルゴリズムは、それらを使用するクライアントとは独立して変化します。
すでに素晴らしい答えに追加するには:戦略パターンは、1つまたは複数の関数を別の関数に渡すことと非常によく似ています。戦略では、これは、オブジェクトで前述の関数をラップし、続いてオブジェクトを渡すことによって行われます。一部の言語は関数を直接渡すことができるため、パターンはまったく必要ありません。しかし、他の言語は関数を渡すことはできませんが、オブジェクトを渡すことはできます。その後、パターンが適用されます。
特にJavaのような言語では、言語のタイプzooはかなり小さく、それを拡張する唯一の方法はオブジェクトを作成することです。したがって、問題のほとんどの解決策は、パターンを考え出すことです。特定の目標を達成するためにオブジェクトを作成する方法。型動物園が豊富な言語では、問題を解決する方法が簡単になることがよくありますが、型が豊富なため、型システムの学習により多くの時間を費やす必要があります。動的型付けの分野を備えた言語は、問題を回避するために卑劣な方法をとることがよくあります。