【PHPデザインパターン】12_Composite~木構造を表す
引用記事
この記事を書くきっかけになったブログです。
記事内の解説やソースコードは、こちらのブログと著者の公開リポジトリを参考にしています。
Do You PHP はてな〜[doyouphp][phpdp]PHPによるデザインパターン入門 - Composite~木構造を表す
概要
- 「composite」とは「合成物」「混合物」という意味
- 部分〜全体階層を表現するために、オブジェクトを木構造に組み立てる。
- それにより、単体のオブジェクトとオブジェクトの集合を同一視することができる。
- 単一のオブジェクトにも、複数のオブジェクトから形成されたオブジェクトにも、同じ手順でアクセスできるAPIを提供する。
構成要素
Componentクラス
- 直訳すると「成分」「構成要素」。
- Clientクラスに対して共通にアクセスさせるためのAPIを提供するクラス。
- 子に相当するオブジェクトにアクセスしたり、追加・削除するためのAPIも含む。
Leafクラス
- Componentクラスのサブクラス
- 木構造の末端に位置する葉に相当するクラス。
- 子に相当するオブジェクトを持たない。
Compositeクラス
- 直訳すると「複合」。
- Componentクラスのサブクラス。
- 木構造の中で任意枝に相当するクラス。
- 子に相当するオブジェクトを持つ。
- 子に相当するオブジェクトにアクセスしたり、追加・削除するためのAPIを実装する。
Clientクラス
- ComponentクラスのAPIを通して、木構造にアクセスする。
実演
処理の流れ
-
Entryクラス
でクライアントからアクセスできる共通のAPIを定義する。
-
Itemクラス
を枝、Foodクラス
を葉に見立て、メソッドを実装する。
- 階層が多重構造の場合も、再帰処理を行い各要素(Entryクラスのオブジェクト)に対してメソッドを実行する。
ファイル構造
MyComposite
├── Entry.php
├── Food.php
├── Item.php
└── my_client.php
ソースコード
Componentクラス
Entry.php
Entry.php
<?php
namespace DoYouPhp\PhpDesignPattern\Composite\MyComposite;
/**
* Componentクラスに相当する
*/
abstract class Entry
{
private $id;
private $name;
public function __construct($id, $name)
{
$this->id = $id;
$this->name = $name;
}
public function getId()
{
return $this->id;
}
public function getName()
{
return $this->name;
}
// 子要素を追加する
// 抽象メソッドのため、サブクラスで定義する
abstract public function add(Entry $entry);
// idとnameを表示する
public function dump()
{
echo 'ID:'.$this->id.',名前:'.$this->name.'<br>'."\n";
}
}
Leafクラス
Food.php
Food.php
<?php
namespace DoYouPhp\PhpDesignPattern\Composite\MyComposite;
use DoYouPhp\PhpDesignPattern\Composite\MyComposite\Entry;
/**
* Leafクラスに相当する
*/
class Food extends Entry
{
public function __construct($id, $name)
{
parent::__construct($id, $name);
}
// 子要素を追加する
// 抽象メソッドのため、必ず定義する
// Leafクラスは子要素を持たないので、例外を発生させる
public function add(Entry $entry)
{
throw new \Exception('このメソッドは使用できません');
}
}
Compositeクラス
Item.php
Item.php
<?php
namespace DoYouPhp\PhpDesignPattern\Composite\MyComposite;
use DoYouPhp\PhpDesignPattern\Composite\MyComposite\Entry;
/**
* Compositeクラスに相当する
*/
class Item extends Entry
{
private $entries;
public function __construct($id, $name)
{
parent::__construct($id, $name);
$this->entries = array();
}
// 子要素を追加する
public function add(Entry $entry)
{
array_push($this->entries, $entry);
}
// 組織ツリーを表示する
// 自分自身と保持している子要素を表示する
public function dump()
{
// ここでidとnameを表示する
parent::dump();
foreach ($this->entries as $entry) {
// 再帰処理を確認する
// echo '<pre>';
// var_dump($entry);
// echo '</pre>';
// 再帰処理を行い、各要素を表示する
$entry->dump();
}
}
}
Clientクラス
my_client.php
my_client.php
<?php
namespace DoYouPhp\PhpDesignPattern\Composite\MyComposite;
require dirname(dirname(__DIR__)).'/vendor/autoload.php';
use DoYouPhp\PhpDesignPattern\Composite\MyComposite\Item;
use DoYouPhp\PhpDesignPattern\Composite\MyComposite\Food;
// rootを作成する
$root_entry = new Item(1, 'food');
$root_entry->add(new Food(11, 'orange'));
// root直下に加える
$group1 = new Item(2, 'fruits');
$group1->add(new Food(21, 'banana'));
// fruits直下に加える
$group2 = new Item(3, 'red_fruits');
$group2->add(new Food(31, 'apple'));
// red_fruits直下に加える
$group3 = new Item(4, 'red_small_fruits');
$group3->add(new Food(41, 'strawberry'));
$group2->add($group3);
$group1->add($group2);
$root_entry->add($group1);
// food直下に加える
$group4 = new Item(5, 'vegetables');
$group4->add(new Food(51, 'tomato'));
$root_entry->add($group4);
// 構造を出力する
$root_entry->dump();
// Foodクラスはaddメソッドが使用できないことを確認する
try {
$group5 = new Food(52, 'onion');
$group5->add(new Food(53, 'cabbage'));
} catch (\Exception $e) {
echo $e->getMessage();
}
処理の流れ
-
Entryクラス
でクライアントからアクセスできる共通のAPIを定義する。 -
Itemクラス
を枝、Foodクラス
を葉に見立て、メソッドを実装する。 - 階層が多重構造の場合も、再帰処理を行い各要素(Entryクラスのオブジェクト)に対してメソッドを実行する。
ファイル構造
MyComposite
├── Entry.php
├── Food.php
├── Item.php
└── my_client.php
ソースコード
Componentクラス
Entry.php
Entry.php
<?php
namespace DoYouPhp\PhpDesignPattern\Composite\MyComposite;
/**
* Componentクラスに相当する
*/
abstract class Entry
{
private $id;
private $name;
public function __construct($id, $name)
{
$this->id = $id;
$this->name = $name;
}
public function getId()
{
return $this->id;
}
public function getName()
{
return $this->name;
}
// 子要素を追加する
// 抽象メソッドのため、サブクラスで定義する
abstract public function add(Entry $entry);
// idとnameを表示する
public function dump()
{
echo 'ID:'.$this->id.',名前:'.$this->name.'<br>'."\n";
}
}
Leafクラス
Food.php
Food.php
<?php
namespace DoYouPhp\PhpDesignPattern\Composite\MyComposite;
use DoYouPhp\PhpDesignPattern\Composite\MyComposite\Entry;
/**
* Leafクラスに相当する
*/
class Food extends Entry
{
public function __construct($id, $name)
{
parent::__construct($id, $name);
}
// 子要素を追加する
// 抽象メソッドのため、必ず定義する
// Leafクラスは子要素を持たないので、例外を発生させる
public function add(Entry $entry)
{
throw new \Exception('このメソッドは使用できません');
}
}
Compositeクラス
Item.php
Item.php
<?php
namespace DoYouPhp\PhpDesignPattern\Composite\MyComposite;
use DoYouPhp\PhpDesignPattern\Composite\MyComposite\Entry;
/**
* Compositeクラスに相当する
*/
class Item extends Entry
{
private $entries;
public function __construct($id, $name)
{
parent::__construct($id, $name);
$this->entries = array();
}
// 子要素を追加する
public function add(Entry $entry)
{
array_push($this->entries, $entry);
}
// 組織ツリーを表示する
// 自分自身と保持している子要素を表示する
public function dump()
{
// ここでidとnameを表示する
parent::dump();
foreach ($this->entries as $entry) {
// 再帰処理を確認する
// echo '<pre>';
// var_dump($entry);
// echo '</pre>';
// 再帰処理を行い、各要素を表示する
$entry->dump();
}
}
}
Clientクラス
my_client.php
my_client.php
<?php
namespace DoYouPhp\PhpDesignPattern\Composite\MyComposite;
require dirname(dirname(__DIR__)).'/vendor/autoload.php';
use DoYouPhp\PhpDesignPattern\Composite\MyComposite\Item;
use DoYouPhp\PhpDesignPattern\Composite\MyComposite\Food;
// rootを作成する
$root_entry = new Item(1, 'food');
$root_entry->add(new Food(11, 'orange'));
// root直下に加える
$group1 = new Item(2, 'fruits');
$group1->add(new Food(21, 'banana'));
// fruits直下に加える
$group2 = new Item(3, 'red_fruits');
$group2->add(new Food(31, 'apple'));
// red_fruits直下に加える
$group3 = new Item(4, 'red_small_fruits');
$group3->add(new Food(41, 'strawberry'));
$group2->add($group3);
$group1->add($group2);
$root_entry->add($group1);
// food直下に加える
$group4 = new Item(5, 'vegetables');
$group4->add(new Food(51, 'tomato'));
$root_entry->add($group4);
// 構造を出力する
$root_entry->dump();
// Foodクラスはaddメソッドが使用できないことを確認する
try {
$group5 = new Food(52, 'onion');
$group5->add(new Food(53, 'cabbage'));
} catch (\Exception $e) {
echo $e->getMessage();
}
Author And Source
この問題について(【PHPデザインパターン】12_Composite~木構造を表す), 我々は、より多くの情報をここで見つけました https://qiita.com/yukibe/items/7304df59f3692c15c497著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .