Composite Pattern
木構造を持つオブジェクトモデルに適用可能なパターン。O/Rマッピングにおける、単一テーブル上の自己参照結合に適用できる。
<?php /* * オペレーションエラー時の例外クラス */ class FileTreatmentException extends RuntimeException{ function __construct($message){ parent::__construct($message, $code); } } /* * ツリー構造を持つ集合要素の抽象クラス */ abstract class Component{ protected $name; protected $size; /* * プロパティへのアクセッサー */ abstract function name(); /* * プロパティへのアクセッサー */ abstract function size(); /* * * プロパティへのアクセッサー */ abstract function render(); } /* * ツリー構造の葉クラス */ class Leaf extends Component{ function __construct($name, $size){ $this->name = $name; $this->size = $size; } function name(){ return $this->name; } function size(){ return $this->size; } function render(){ echo "<li><b>Name</b>: {$this->name}, <b>Size</b>: {$this->size}</li>\n"; } } /* * ツリー構造の枝クラス */ class Composite extends Component{ protected $children = array(); function __construct($name){ $this->name = $name; } function name(){ return $this->name; } function size(){ foreach($this->children as $component){ $this->size += $component->size(); } return $this->size; } function render(){ echo "<p>{$this->name}</p>\n"; echo "<ul>\n"; foreach($this->children as $component){ $component->render(); } echo "</ul>\n"; } /* * エントリーオペレーション * エントリーを追加する */ function add(Component $component){ $this->children[$component->name()] = $component; } /* * エントリーオペレーション * エントリーを削除する */ function remove(Component $component){ unset($this->children[$component->name()]); } /* * エントリーオペレーション * エントリーを取得する */ function children(){ return $this->children; } } $leaf_1 = new Leaf("椿", 234); $leaf_2 = new Leaf("松", 195); $leaf_3 = new Leaf("樫", 3298); $leaf_4 = new Leaf("楢", 275); $eda_1 = new Composite("枝"); $eda_1->add($leaf_1); $eda_1->add($leaf_2); $eda_2 = new Composite("枝2"); $eda_2->add($leaf_3); $eda_1->add($leaf_4); $eda_1->add($eda_2); $eda_1->render(); $eda_2->add("hoge");//Catchable fatal errorが発生 ?>