PHPのデザインパターン
プログラムにおける常套句ってやつなのかな。
PHP以外のプログラムでも考え方として使えるからとりあえずここら辺はおさえておきたいところ。
ただコレを知ってれば良いってわけでもなく結局ケースバイケースだとは思うけど、技としてはこういうの大事ね。
【Singleton】
全体で同じ物を使い回すためのクラス。オブジェクトの数が1つ、または一定の少数の場合に使う。
例はDBのコネクション
class MyDbConnection {
protected static $dbConnection;
protected function __construct()
{
self::$dbConnection = new PDO("sqlite:db.sqlite","","");
}
public static function getDbConnection()
{
if(!self::$dbConnection) {
self::$dbConnection = new self();
}
return self::$dbConnection;
}
}
コンストラクタがprotectedになっている。
クラス自体をnewできないので、staticで保存された値が全インスタンスで共有される。
【Abstract Factory】
受け取った値や、現在の状況で返すオブジェクトを生成するためのクラス。
例は自動販売機
class Factory
{
public static function createProduct($type, $name, $price)
{
switch($type) {
case 'Cola' :
return new Cola($name, $price);
break;
case 'Tea' :
return new Tea($name, $price);
break;
default :
return null;
break;
}
}
}
もっとFactoryClassに条件分岐いれたりするといい。
$cocacola = Factory::createProduct("Cola", "コカコーラ", 120);
$heytea = Factory::createProduct("Tea", "お〜い!お茶",150);
【Composite】
再帰的な構造を表現する。
/* スーパークラス */
abstract class DirectoryFile
{
protected $name;
public function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
abstract public function add(DirectoryFile $child);
abstract public function remove(DirectoryFile $child);
abstract public function getChildren();
abstract public function display($level);
}
/* サブクラス - File */
class File extends DirectoryFile
{
/* ファイルの場合,add/removeできない */
public function add(DirectoryFile $child)
{
echo("ファイルには子要素は追加できません");
return null;
}
public function remove(DirecotryFile $child)
{
echo("ファイルには子要素がありません")
return null;
}
public function getChildren()
{
return null;
}
public function display($level)
{
echo (str_repeat(' ', $level) . $this->name . "\n");
}
}
/* サブクラス - Dir */
class Dir extends DirectoryFile
{
private $files;
public function __construct($name)
{
praent::__construct($name);
$this->files = array();
}
public function add(DirectoryFile $child)
{
$this->files[] = $child;
return $this; //自分を返すことでチェーンできる。
}
public function remove(DirecotryFile $child)
{
return array_splice($this->files, array_search($child, $this->files, true), 1);
}
public function getChildren()
{
return $this->files;
}
public function display($level)
{
echo (str_repeat(' ', $level) . $this->name . "\n");
foreach($this->files as $child)
{
$child->display($level + 1);
}
}
}
【Iterator】
反復を隠蔽するパターン。
IteratorとIteratorAggregateはPHPの内部実装なので書かなくてもいいですが、以下のようになっています。
interface Iterator
{
public function rewind();
public function next();
public function current();
public function valid();
public function key();
}
interface IteratorAggregate
{
public function getIterator();
}
Iteratorを使ったクラス定義をします。
class NominalList implements IteratorAggregate
{
private $members;
public function __construct()
{
$this->members = array();
}
public function add($member)
{
$this->members[] = $member;
}
public function getMember($index)
{
if ( $index < 0 || $index >= count($this->members) ) {
return null;
} else {
return $this->members[$index];
}
}
public function getIterator()
{
return new NominalListIterator($this);
}
}
class NominalListIterator implements Iterator
{
private $index = 0;
private $obj;
public function __construct(NominalList $obj)
{
$this->obj = $obj;
}
public function rewind()
{
$this->index = 0;
}
public function next()
{
$this->index += 1;
}
public function current()
{
return $this->obj->getMember($this->index);
}
public function valid()
{
return ( $this->obj->getMember($this->index) ? true : false );
}
public function key()
{
return $this->index;
}
}
こうすることで、NominalListがIteratorインターフェイスに沿っているので、
NominalListにaddした値を取得することができます。
$nl = new NominalList();
$nl->add("foo");
$nl->add("bar");
$nl->add("hoge");
foreach($nl as $key => $val) {
echo $key . " = " . $val . "\n";
}
Iteratorはちょっと難しいのでこの辺をみるといいかも。
http://d.hatena.ne.jp/hnw/20090523



