3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHPで使うGoFパターン ひとり Advent Calendar - コンポジット

Last updated at Posted at 2012-08-17

コンポジットってなに?

再帰的に内包される内容物と器を同一視するということですね。はい、さっぱり分からない。要するにディレクトリもファイルもシンボリックリンクも同じように扱うということです。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 ();
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?