コンピュータプログラミングにおいて、戦略パターン(ポリシーパターンとも呼ばれる)は、実行時にアルゴリズムを選択できるようにする動作 ソフトウェア設計パターンです。単一のアルゴリズムを直接実装する代わりに、コードはアルゴリズムのファミリのどれを使用するかについての実行時指示を受け取ります。[1]
戦略により、アルゴリズムはそれを使用するクライアントとは独立して変化します。[2]戦略は、 Gamma らによる影響力のある書籍「デザイン パターン」 [3]に含まれるパターンの 1 つで、柔軟で再利用可能なオブジェクト指向ソフトウェアを設計する方法を説明するためにデザイン パターンを使用するという概念を普及させました。どのアルゴリズムを使用するかの決定を実行時まで延期することで、呼び出しコードの柔軟性と再利用性を高めることができます。
たとえば、受信データの検証を実行するクラスは、戦略パターンを使用して、データの種類、データのソース、ユーザーの選択、またはその他の識別要因に応じて検証アルゴリズムを選択することができます。これらの要因は実行時まで不明であり、まったく異なる検証を実行する必要がある場合があります。検証オブジェクトとは別にカプセル化された検証アルゴリズム (戦略) は、コードの重複なしに、システムの異なる領域 (または異なるシステム) にある他の検証オブジェクトによって使用できます。
通常、戦略パターンは、コードへの参照をデータ構造に格納し、それを取得します。これは、ネイティブ関数ポインター、ファーストクラス関数、オブジェクト指向プログラミング言語のクラスまたはクラスインスタンスなどのメカニズム、またはリフレクションを介して言語実装の内部コードストレージにアクセスすることによって実現できます。
構造
UML クラス図とシーケンス図

上記のUML クラス図では、Contextクラスはアルゴリズムを直接実装していません。 代わりに、はアルゴリズムを実行するためのインターフェイス ( )Contextを参照します。このインターフェイスは、アルゴリズムの実装方法とは無関係です。 クラスとクラスはインターフェイスを実装します。つまり、アルゴリズムを実装 (カプセル化) します。
UMLシーケンス図は、
実行時の相互作用を示しています。 オブジェクトは、アルゴリズムをさまざまなオブジェクトに委任します。最初に、 はオブジェクトを呼び出します。このオブジェクトはアルゴリズムを実行し、結果を に返します。その後、は戦略を変更し、オブジェクトを呼び出します。このオブジェクトはアルゴリズムを実行し、結果を に返します。
Strategystrategy.algorithm()ContextStrategy1Strategy2Strategy
ContextStrategyContextalgorithm()Strategy1ContextContextalgorithm()Strategy2Context
クラス図

[5]

戦略とオープン/クローズ原則

戦略パターンによれば、クラスの動作は継承されるべきではありません。代わりに、インターフェイスを使用してカプセル化する必要があります。これは、クラスは拡張に対してはオープンであるが、変更に対してはクローズであるべきであると提案する オープン/クローズ原則(OCP) と互換性があります。
例として、自動車クラスを考えてみましょう。自動車には、ブレーキと加速という 2 つの機能があります。加速とブレーキの動作はモデル間で頻繁に変わるため、これらの動作をサブクラスで実装するのが一般的な方法です。この方法には大きな欠点があります。加速とブレーキの動作は、新しい自動車モデルごとに宣言する必要があります。モデルの数が増えると、これらの動作を管理する作業が大幅に増え、モデル間でコードを複製する必要があります。さらに、各モデルのコードを調べずに、各モデルの動作の正確な性質を判断するのは簡単ではありません。
戦略パターンは継承の代わりに合成を使用します。戦略パターンでは、動作は個別のインターフェースと、これらのインターフェースを実装する特定のクラスとして定義されます。これにより、動作と動作を使用するクラス間の分離が向上します。動作は、それを使用するクラスを壊すことなく変更できます。また、クラスは、大幅なコード変更を必要とせずに、使用される特定の実装を変更することで動作を切り替えることができます。動作は、実行時だけでなく設計時にも変更できます。たとえば、自動車オブジェクトのブレーキ動作は、メンバーを次のように変更することでBrakeWithABS()からに変更できます。
Brake()brakeBehavior
brakeBehavior =新しいブレーキ();
/* カプセル化されたアルゴリズムのファミリー
* インターフェースとその実装
*/
public interface IBrakeBehavior { public void brake (); }
public class BrakeWithABS はIBrakeBehaviorを実装します{ public void brake () { System . out . println ( "ABS を適用したブレーキ" ); } }
public class Brake はIBrakeBehaviorを実装します{ public void brake () { System . out . println ( "Simple Brake applied" ); } }
/* 上記のアルゴリズムを互換的に使用できるクライアント */
public abstract class Car { private IBrakeBehavior brakeBehavior ;
パブリックCar ( IBrakeBehavior brakeBehavior ) { this . brakeBehavior = brakeBehavior ; }
パブリックvoid applyBrake () { brakeBehavior.brake ( ) ; }
public void setBrakeBehavior ( IBrakeBehavior BrakeType ) { this .ブレーキ動作=ブレーキタイプ; } }
/* クライアント 1 はコンストラクターで 1 つのアルゴリズム (ブレーキ) を使用します */
public class Sedan extends Car { public Sedan () { super ( new Brake ()); } }
/* クライアント 2 はコンストラクターで別のアルゴリズム (BrakeWithABS) を使用します */
public class SUV extends Car { public SUV () { super ( new BrakeWithABS ()); } }
/* Car の例を使用する */
public class CarExample { public static void main ( final String [] arguments ) { Car sedanCar = new Sedan (); sedanCar . applyBrake (); // これはクラス "Brake" を呼び出します
Car suvCar = new SUV (); suvCar . applyBrake (); // これはクラス "BrakeWithABS" を呼び出します
// ブレーキの動作を動的に設定する
suvCar . setBrakeBehavior ( new Brake () ); suvCar . applyBrake (); // これにより、クラス "Brake" が呼び出されます} }
参照
参考文献
- ^ 「戦略デザインパターン - 問題、解決策、適用性」w3sDesign.com 。 2017年8月12日閲覧。
- ^ Eric Freeman、Elisabeth Freeman、Kathy Sierra、Bert Bates、「Head First Design Patterns 」、初版、第 1 章、24 ページ、O'Reilly Media, Inc、2004 年。ISBN 978-0-596-00712-6
- ^ Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides (1994)。デザインパターン: 再利用可能なオブジェクト指向ソフトウェアの要素。Addison Wesley。pp. 315ff。ISBN 0-201-63361-2。
{{cite book}}: CS1 maint: 複数の名前: 著者リスト (リンク) - ^ 「戦略デザインパターン - 構造とコラボレーション」w3sDesign.com 。 2017 年 8 月 12 日閲覧。
- ^ 「デザインパターンクイックリファレンス – McDonaldLand」。
外部リンク
- UML の戦略パターン(スペイン語)
- Geary, David (2002 年 4 月 26 日)。「成功のための戦略」。Java デザイン パターン。JavaWorld。2020年7 月 20 日閲覧。
- C 記事の戦略パターン
- リファクタリング: 型コードを状態/戦略に置き換える
- Wayback Machineの Strategy Design Pattern (アーカイブ 2017-04-15) JavaScript での Strategy パターンの実装
