容器と中身の同一視。
ファイルシステムでは、ディレクトリとファイルが入れ子になっている。
ディレクトリとファイルは異なるものですが、「ディレクトリに入るもの」とみなしている。
Leaf(葉):MyFile
中身
Composite(複合体):MyDirectory
容器
Component:Entry
LeafとCompositeを同一視するためのスーパークラス。
Client(依頼者):Main
他にも複数と単数の同一視など。
Entry.php
abstract class Entry { abstract function getName(); abstract function getSize(); function add(Entry $entry) { throw new Exception("FileTreatmentException"); } abstract function printList($prefix=null); function toString() { return $this->getName() . "(" . $this->getSize() . ")"; } }
MyFile.php
class MyFile extends Entry { private $name; private $size; function __construct(String $name, int $size) { $this->name = $name; $this->size = $size; } function getName() { return $this->name; } function getSize() { return $this->size; } function printList($prefix=null) { echo $prefix . "/" . $this->toString() . "\n"; } }
MyDirectory.php
class MyDirectory extends Entry { private $name; private $directory = []; function __construct(String $name) { $this->name = $name; } function getName() { return $this->name; } function getSize() { $size = 0; foreach ($this->directory as $entry) { $size += $entry->getSize(); } return $size; } function add(Entry $entry) { $this->directory[] = $entry; return $this; } function printList($prefix=null) { echo $prefix . "/" . $this->toString() . "\n"; foreach ($this->directory as $entry) { $entry->printList($prefix . "/" . $this->name); } } }
Main.php
require "../autoload.php"; echo "Making root entries...\n"; $rootdir = new MyDirectory("root"); $bindir = new MyDirectory("bin"); $tmpdir = new MyDirectory("tmp"); $usrdir = new MyDirectory("usr"); $rootdir->getName(); $rootdir->add($bindir); $rootdir->add($tmpdir); $rootdir->add($usrdir); $bindir->add(new MyFile("vi", 10000)); $bindir->add(new MyFile("latex", 20000)); $rootdir->printList();