2012年2月2日木曜日

AmidaMVC:アミダ式チェーンとChain of Responsibilityパターン

Amida式Chainのコードです。


function dispatch( $action, &$data=NULL ) {
    // set current action.
    $return = NULL;
    $this->_dispatchAct = $action;
    $this->setAction( $action );
    $this->fireStart();
    // -----------------------------
    // chain of responsibility loop.
    while( $this->moreModels() )     {
        $this->fireDispatch();
        $action = $this->getAction();
        $return = $this->execAction( $action, $data, $return );
        if( $this->useNextComponent() ) {
            // go to next component. 
            $this->nextComponent();
        }
        else {
            $this->useNextComponent( TRUE ); // reset to TRUE. 
        }
    }
    // -----------------------------
    return $return;
}


内部に$this->_componentsという配列にコンポーネントを登録しておいてwhile文でループしているだけです。

コンポーネントの扱い

nextComponent()でarray_sliceをして、
次のコンポーネントに進みます。つまり、後へは戻れません。

ただしコンポーネント内で別のコンポーネントを登録できます。
例:prependComponent( 'appHello', 'app' );

これで自分自身の次に実行するコンポーネントを追加します。
その他、チェーンの最後に追加する、チェーンを終了するする、指定したコンポーネントまでスキップする、などが出来ます(まだAPIで全てに対応はしてませんが)。

アクションの扱い

$actionはコンポーネント内で必要に応じて変更されます。それ以外は変わらず同じアクション(つまり同じ名前のメソード)を呼び続けます。

Chain of Responsibilityパターン

Amida式チェーンは、Chain of Responsibility (CoR)パターンの一種だと思ってます。WikipediaでのCoRのページを見てもよく分かりません。

自分の理解では、何かを達成するのに複数のオブジェクトを使う、複数のオブジェクトを使うためにAPIを共通にする、そして実行するオブジェクトの順番を適宜変更できるようにする、というパターンだと思ってます。

なのでCoRの実装方法はいろいろあると思います。
多分、LithiumというPHPのフレームワークは、各オブジェクト内で次に呼ぶオブジェクトを指定しているようです。リンクトリストみたいですね。

それに比べるとAmida式チェーンは比較的単純だと思います。実行するオブジェクト(あるいはクラス)を最初に配列で持っています。一方、途中でオブジェクトの順番を変えたり、呼び出すメソード名を変更できるのが特徴です。


0 件のコメント: