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が発生

?>