🗂
# デザインパターンを学ぶ #9 コンポジット(Composite)
1. はじめに
デザインパターン学習シリーズの第8回。今回は Composite(コンポジット)パターンを取り上げます。
目的は 部分(Leaf)と全体(Composite)を同一視して扱えるようにする 方法を理解することです。
2. Compositeとは
Compositeパターンは、個と集合を同じインターフェースで扱う設計です。
ツリー構造(階層構造)を意識せずに操作できるため、フォルダとファイル、カテゴリと商品などをまとめて扱いたい場面で有効です。
3. 構成要素
- Component:共通インターフェース
- Leaf:子を持たない末端要素
- Composite:複数の子(Component)を保持し、操作を子に再帰的に委譲する
4. 実装例(PHP)
<?php
interface Item {
public function getPrice(): int;
public function getName(): string;
}
final class Product implements Item {
public function __construct(
private string $name,
private int $price
) {}
public function getPrice(): int { return $this->price; }
public function getName(): string { return $this->name; }
}
final class ProductGroup implements Item {
/** @var Item[] */
private array $children = [];
public function __construct(private string $name) {}
public function add(Item $item): void {
$this->children[] = $item;
}
public function getPrice(): int {
return array_sum(array_map(fn($c) => $c->getPrice(), $this->children));
}
public function getName(): string { return $this->name; }
}
// 利用例
$ramen = new Product('ラーメン', 800);
$gyoza = new Product('餃子', 300);
$set = new ProductGroup('セットA');
$set->add($ramen);
$set->add($gyoza);
echo $set->getName() . ' 合計: ' . $set->getPrice() . "円\n";
// 出力: セットA 合計: 1100円
5. 使いどころ
- 商品カテゴリ・フォルダ・組織図などのツリー構造
- 店舗グループやチーム階層など、部分集合の値を親で集計したい場面
6. メリット
- 個と集合を同じように扱える
- クライアント側の
if分岐をなくせる - 再帰処理でツリー構造を自然に表現できる
7. 注意点
- ツリー構造でないものに無理に適用すると過剰設計になりやすい
- 深い階層での再帰集計はパフォーマンス問題になりやすい(キャッシュや差分更新を検討する)
8. まとめ
Compositeは「部分と全体を同一視して扱う」構造パターンです。
次回は関連する構造パターンのProxy に進むと理解がつながりやすいです。
Discussion