|
オブジェクト指向についてはまだまだ勉強中ですが、「PHPでGoFのデザインパターンを実装したら、どんな感じになるんだろ?」と思ってしまったので、ちょっとずつやってみることにしました。
間違いやご意見がありましたら、遠慮なくツッコミを入れてくださいm(_"_)m
今回は、Chain of Responsibilityパターンで「複数のオブジェクトをチェーンにしておき、目的のオブジェクトを決定させる」パターンです(以下のクラス図を参照)。
今回のサンプルは、与えられた文字がどんな文字種かどうかを調べるものです。具体的には以下の3つになります。
- 数字のみ
- アルファベット(大文字小文字)
- 携帯電話番号(xxx-xxxx-xxxx)
これらをConcreteHandlerとして用意しました。上のクラス図との関係は、以下のようになります。
- Handler => CheckHander
- ConcreteHander => NumberCheckHandler/AlphabetCheckHandler/MobileNumberCheckHandler
ということで、以下がサンプルコードです。
●ChainOfResponsibility.php
<?php
class CheckHandler
{
var $next_;
function &setNext(&$next)
{
$this->next_ = $next;
return $this->next_;
}
function getNext()
{
return $this->next_;
}
function check($variable)
{
if ($this->checked($variable)) {
echo $variable . ":checked by " . get_class($this) . "<BR>";
}
else if (isset($this->next_)) {
$this->next_->check($variable);
}
else {
echo $variable . ":unknown<BR>";
}
}
function checked($variable)
{
}
}
class NumberCheckHandler extends CheckHandler
{
function checked($variable)
{
return preg_match("/^[0-9]+$/", $variable);
}
}
class AlphabetCheckHandler extends CheckHandler
{
function checked($variable)
{
return preg_match("/^[a-z]+$/i", $variable);
}
}
class MobileNumberCheckHandler extends CheckHandler
{
function checked($variable)
{
return preg_match("/^0[0-9]0-[0-9]{4}-[0-9]{4}$/", $variable);
}
}
?>
<?php
$ch = new CheckHandler();
$cn = new NumberCheckHandler();
$ca = new AlphabetCheckHandler();
$cm = new MobileNumberCheckHandler();
$cn =& $ch->setNext(&$cn);
$ca =& $cn->setNext(&$ca);
$cm =& $ca->setNext(&$cm);
$tmp = $ch->getNext();
echo "\$tmp=".get_class($tmp)."<br/>";
$tmp = $tmp->getNext();
echo "\$tmp=".get_class($tmp)."<br/>";
$tmp = $tmp->getNext();
echo "\$tmp=".get_class($tmp)."<br/>";
$tmp = $tmp->getNext();
echo "\$tmp=".get_class($tmp)."<br/>";
$ch->check("090-1234-5678");
$ch->check("09012345678");
$ch->check("chain_of_responsibility");
$ch->check("hoge");
?>
●出力結果
$tmp=checknumber
$tmp=numbercheckhandler
$tmp=alphabetcheckhandler
$tmp=mobilenumbercheckhandler
$tmp=
090-1234-5678:checked by mobilenumbercheckhandler
09012345678:checked by numbercheckhandler
chain_of_responsibility:unknown
hoge:checked by alphabetcheckhandler
Javaでは処理チェーンを作成するときに「ch.setNext(cn).setNext(ca).setNext(cm)」のような感じで書けるのですが、PHPでは「parse error」になってしまいます。んー。残念。。。なお、setNextメソッドのメソッドの引数・戻り値は参照での受け渡しとなります。
[2002/02/28] メソッドではなくコンストラクタでチェーンを作成するバージョンを、ひろしさん@PHPカイハツが旧サイトのBBSに書いています。そちらも参照してみてください。
また、今回は実際のチェック処理メソッド(checked)をHandlerで定義、ConcreteHandlerで実装していますが、Compositeパターンの時にも書いたとおり、Javaのabstractようにメソッドのオーバーライドが強制されないので、実装側で注意が必要です。
[2002/03/09] こちらに「abstractメソッドの実装を強制」させることについてまとめています
|