コンポジットってなに?
再帰的に内包される内容物と器を同一視するということですね。はい、さっぱり分からない。要するにディレクトリもファイルもシンボリックリンクも同じように扱うということです。XMLのノードもアトリビュートも同じように扱うということです。組織図の中の部署に部長を立てて人間として扱い、課も係も、それぞれ代表を立てて、属する社員と同じように扱うということです。会社を法人として扱い、その中に属する社員も人間として扱うので同じように扱うことになるということです。抽象論としてはそんなところですね。天井も床も擬人化することでヤオイすることが出来るということです。要するに擬人化です。そういうことです。擬人化パターンと覚えておくと良いと思います。
コンポジットの構造
このパターンを説明するサンプルコードは大体ファイルシステムを例にとるので反逆しようと思ったのですが、他に良い例が思い付かなかったので、やっぱりファイルシステムにします。これが大人になるということですね。
- 共通インターフェース - 擬人化して同一視するための鍵ですね。インターフェースです。
- 実クラス達 - 擬人化されたいオブジェクト達です
<?php
interface IRemovable {
public function remove ();
}
class Directory implements IRemovable{
public function __construct ( $path ) {
if ( !is_dir ( $path ) )
throw new Exception ( 'ディレクトじゃないもん' );
$this->_Path = preg_replace ( '#/$#', '', $path );
}
public function getList () {
$result = array ();
$d = opendir ( $this->_Path );
while ( $f = readdir ( $d ) ) {
if ( preg_match ( '#^\.+$#', $f ) ) continue;
$path = $this->_Path . '/' . $f;
if ( is_file ( $path ) ) $result[] = new File ( $path );
elseif ( is_dir ( $path ) ) $result[] = new Directory ( $path );
else throw new Exception ( 'ファイルでもディレクトリでもないもん' );
}
return $result;
}
public function remove () {
foreach ( $this->getList () as $obj ) $obj->remove();
rmdir ( $this->_Path );
}
public function makeDirectory ( $name ) {
mkdir ( $this->_Path . '/' . $name );
}
}
class File implements IRemovable {
public function __construct ( $path ) {
if ( !is_file ( $path ) ) throw new Exception ( 'ファイルじゃないもん' );
$this->_Path = preg_replace ( '#/$#', '', $path );
}
public function remove () {
unlink ( $this->_Path );
}
public function saveFile ( $name, $data ) {
file_put_contents ( $this->_Path . '/' . $name, $data );
}
}
$dir = new Directory ( '/etc/tmp' );
// これで /etc/tmp 以下にファイルが有ろうとディレクトリが有ろうと、
// 全部削除出来ますね。
$dir->remove ();