Strategyパターンとは
アルゴリズムをカプセル化して交換可能にする。
Strategyパターンを使うと、アルゴリズムを利用するクライアントとは独立してアルゴリズムを変更できる。
「同じようなことしてるけど、少しやり方が違う」というときに、Strategy パターンでうまく分離できると、見通しがよくなって保守しやすくなる。
Strategyパターンが有効な場面
状況 | 有効な理由 |
---|---|
条件分岐が多くて読みにくい | 処理をクラスに分離できる |
実行時に処理を切り替えたい | Strategyを差し替えるだけでOK |
共通の処理と可変の処理が混ざっている | 共通部分はContextに、可変部分はStrategyに分けられる |
テストをしやすくしたい | Strategyごとに単体テストできる |
Javaの例
アルゴリズムを保持するインターフェース型の変数をクラスで保持しておき、クラスをnewする際に、コンストラクタ引数にインターフェースの実装クラスを指定することで、使用するアルゴリズムを動的に切り替えることを実現している。
package org.wikipedia.patterns.strategy;
// MainApp test application
class MainApp {
public static void main(String[] args) {
Context context;
// 異なるアルゴリズムに従う3つのコンテキスト。
context = new Context(new ConcreteStrategyA());
context.execute();
context = new Context(new ConcreteStrategyB());
context.execute();
context = new Context(new ConcreteStrategyC());
context.execute();
}
}
// 具体的な戦略を実装するクラスは、このインターフェイスを実装する。
// コンテキストクラスは、具体的な戦略を呼び出すためにこのインターフェイスを使用する。
interface Strategy {
void execute();
}
// Strategy インターフェイスを用いたアルゴリズムの実装。
class ConcreteStrategyA implements Strategy {
public void execute() {
System.out.println("Called ConcreteStrategyA.execute()");
}
}
class ConcreteStrategyB implements Strategy {
public void execute() {
System.out.println("Called ConcreteStrategyB.execute()");
}
}
class ConcreteStrategyC implements Strategy {
public void execute() {
System.out.println("Called ConcreteStrategyC.execute()");
}
}
// ConcreteStrategy を指定して作成され、Strategy オブジェクトへの参照を保持する。
class Context {
Strategy strategy;
// Constructor
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void execute() {
this.strategy.execute();
}
}