Strategy パターン

Java

Javaではクラスのメソッドオーバーライドによるポリモーフィズムを使ってStrategyパターンを実現することができる。インターフェイスを用いた例を示す。
package org.wikipedia.patterns.strategy;// MainApp test applicationclass 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();
    }}

Python

Python では関数が第一級オブジェクトであり、このパターンを明示的に定義する必要はない。下記はコールバック関数を用いる GUI プログラミングで見られる例である。
class Button:
    """A very basic button widget."""
    def __init__(self, submit_func, label):
        self.on_submit = submit_func   # strategy 関数を直接生成
        self.label = label# 異なる戦略を持つ2つのインスタンスを作成button1 = Button(sum, "Add 'em")button2 = Button(lambda nums: " ".join(map(str, nums)), "Join 'em")# ボタンをテストするnumbers = range(1, 10) # A list of numbers 1 through 9print button1.on_submit(numbers) # displays "45"print button2.on_submit(numbers) # displays "1 2 3 4 5 6 7 8 9"

C#

C#はJava同様にクラスやインターフェイスによるポリモーフィズムを用いることもできるが、カスタマイズポイントがひとつのメソッドしかない場合（オブジェクトの他のプロパティやメソッドにアクセスしない場合）は、継承関係を必要としないデリゲートを使うほうが好まれる。
using System;// MainApp テストアプリケーション。public class MainApp{
    public static void Main()
    {
        Context context;

        // 異なるアルゴリズムに従う3つのコンテキスト。
        context = new Context(new ConcreteStrategyA().Execute);
        context.Execute();

        context = new Context(new ConcreteStrategyB().Execute);
        context.Execute();

        context = new Context(new ConcreteStrategyC().Execute);
        context.Execute();
    }}// 具体的な戦略を実装するクラスは、このデリゲートに適合するメソッドを実装する。// コンテキストクラスは、具体的な戦略を呼び出すためにこのデリゲートを使用する。public delegate void ExecuteStrategyDelegate();class ConcreteStrategyA{
    public void Execute()
    {
        Console.WriteLine("Called ConcreteStrategyA.Execute()");
    }}class ConcreteStrategyB{
    public void Execute()
    {
        Console.WriteLine("Called ConcreteStrategyB.Execute()");
    }}class ConcreteStrategyC{
    public void Execute()
    {
        Console.WriteLine("Called ConcreteStrategyC.Execute()");
    }}// ExecuteStrategyDelegate オブジェクトへの参照を保持する。class Context{
    ExecuteStrategyDelegate executeStrategy;

    // Constructor
    public Context(ExecuteStrategyDelegate executeStrategy)
    {
        this.executeStrategy = executeStrategy;
    }

    public void Execute()
    {
        this.executeStrategy();
    }}
なお、Javaもバージョン8以降であれば、メソッド参照と関数型インターフェイス (functional interface) を用いることで、C#と類似の実装が可能となる。

Strategy パターンと Bridge パターン

Strategy パターンの UML クラス図は Bridge パターンのものと同じである。しかし、これら二つのデザインパターンはその意図が同じではない。Strategy パターンは振る舞いに対するパターンであるが、Bridge パターンは構造に対するパターンである。
一般にコンテキストと戦略との結合は、Bridge パターンにおける抽象化と実装の結合より強固である。

Strategy パターンと開放/閉鎖原則

Strategy パターンに従うと、クラスの振る舞いは継承されるべきではなく、インターフェイスを用いてカプセル化するべきである。例として Car クラスを考えると、Car の振る舞いにはブレーキとアクセルがある。
アクセルとブレーキの振る舞いはモデルにより大きく異なるため、良くあるアプローチはこれらの振る舞いをサブクラスとして実装することであるが、このアプローチには大きな問題点がある。すなわち、アクセルとブレーキの振る舞いは、新たな Car モデルごとに宣言されなければならない。これはモデルが少ないときには問題にならないが、モデルの数が増えるにつれ、それらの振る舞いを管理する作業が大幅に増加し、またコードがモデル間で重複することになる。さらに、各コードを詳しく分析しなければそれぞれのモデル用の振る舞いの性質を知ることができない。
これに対して Strategy パターンでは、継承ではなく合成 (composition) を用いる。Strategy パターンにおける振る舞いは別々のインターフェイスと、これらのインターフェイスを実装した抽象クラスとして定義される。具体的なクラスは、これらのインターフェイスをカプセル化する。これにより、振る舞いと、それを用いるクラスがうまく分離できる。振る舞いは、それを用いるクラスに変更を加えずに変更することができ、クラスは大きなコード変更を必要とすることなく、使用する実装を切り替えることで振る舞いを切り替えることができる。振る舞いは設計時にも実行時にも変更することができる。例として、Car オブジェクトのブレーキの振る舞いを、メンバー brakeBehavior を BrakeWithABS から Brake に変えることで変更できる：
brakeBehavior = new Brake(); 
これにより設計に優れた柔軟性をもたせることができ、かつ拡張に対して開放的であり変更に対して閉鎖的であるべきとする開放/閉鎖原則 (Open/Closed Principle, OCP) とも調和を保つことができる。