チェインオブレスポンシビリティパターン¶
前章では範囲チェックバリデータに対して継承によって偶数奇数チェックを行うチェック機能をスタックに追加した.しかし偶数奇数チェックだけでなく他のバリデータも追加したくなるかもしれない.
仮に2種類のバリデータAとBがあったら,これらを単独に使用するケース以外にA->B、B->Aの2ケースも考えられるので,これらを継承で解決しようとすると合計で4つのクラスが必要になる.バリデータの数が増えるとこの組み合わせの個数は爆発的に増えてしまう.
この問題には Chain of Responsibility
パターンを利用することで対処できる.このパターンではオブジェクトを数珠つなぎにしておいて,一方の端に処理を依頼する.処理を依頼されたオブジェクトは自分に処理が可能な処理であれば自分で処理して結果を返すが,もし自分には処理できないと判断したら次のオブジェクトに処理を依頼する.このようにしてオブジェクトをチェインしていく.
typedef struct ChaindValidator{
Validator base;
Validator *pWapped;
Validator *pNext;
} ChainedValidator
ChainedValidator
はそれ自身検証機能を持たず,pWrapped
と pNext
を用いて検証を行う.
bool ValidateChain(Validator *p, int val){
ChainedValidator *pThis = (ChainedValidator *)p;
p = pThis->pWrapped;
if(!p->validate(p, val)) return false;
p = pThis->pNext;
if(p == NULL) return true;
return p->validate(p, val);
}
処理の流れは
- まず
pWrapped
で指されれているバリデータを用いて検証し,falseが返ればそのままfalseを返す(検証失敗). - もしtrueを返したら,次に
pNext
を調べる. - もし
pNext
がNULLだったら,今までのバリデータが全てtrueを返したことになる.よってtrueを最後に返す. - もし
pNext
がNULLでなければpNext
に処理を委ねる.
実装の注意点としては,このチェインにループが含まれてはいけないことである.