Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

Strategyパターン

概要

このパターンはアルゴリズムをクラス化してクライアントからクラスの切り替えで処理を行うパターンになります。
クライアントからのアクセス用の共通メソッド(API)を用意してあげて、別々のクラスのメソッドにアクセスをして
完全に処理クラスに委譲することができます。
またこのパターンを利用するとContext内部でif else分などの条件文をすっきりさせることができます。

Strategyクラス

<?php

//Strategy interface
interface Strategy {
    public function calculate( array $array );
}

//Strategy interfaceの実装
class SumCalculator implements Strategy {

    //計算の実行
    public function calculate( array $data ) {
        $sum = 0;
        foreach( $data as $value ) {
            $sum += $value;
        }
        return $sum;
    }

}

//Strategy interfaceの実装
class MultiplyCalculator implements Strategy {

    //計算の実行
    public function calculate( array $data ) {
        $sum = array_shift( $data );
        foreach( $data as $value ) {
            $sum *= $value;
        }
        return $sum;
    }
}

このように共通Interfaceを用いて計算処理を行う個別クラスにアルゴリズムを記述します。

Contextクラス

<?php
// Strategyインスタンスを実行するContext
class Subject {
    private function __construct(){}
    public static function calculate( Strategy $strategy, array $data ) {
        return $strategy->calculate( $data );
    }
}

ストラテジークラスのcalculate処理を呼び出すContextクラスを用意します。クライアントからはContextクラスを呼び出します。

client

<?php
// client
$data = array( 1, 2, 3, 4, 5);
$val = Subject::calculate( new SumCalculator(), $data );
echo "$val \n";

$val = Subject::calculate( new MultiplyCalculator(), $data ); 
echo "$val \n";

クライアントからは何の処理を実行するかという情報を与えてあげるだけで済みます。

実行結果

15
120

その他使用例

以前紹介したvalidatorの処理が似ているかもしれません。
http://d.hatena.ne.jp/jogriko/20100923