
「構造パターン」の代表格、Composite(コンポジット)パターンについて解説します。
ツリー構造(階層構造)を扱う設計で、とてもよく使われるパターンです。
目的は、「個(オブジェクト)」と「集合(グループ)」を同じように扱えるようにすること。
イメージとしては、フォルダとファイルを、どちらも「開く」「削除する」といった同じ操作で扱えます。
「木構造(ツリー)」を再帰的に構築できるようにするためのデザインパターンですね。
よくある例
・OSのファイルシステム(フォルダとファイル)
・HTMLのDOMツリー(親要素と子要素)
・組織図(部門と社員)
| 分野 |
Compositeの実例 |
| Web |
DOMツリー(ElementとNodeList) |
| GUI |
メニュー構造、ボタンやパネルの入れ子 |
| ファイル操作 |
OSのフォルダ・ファイル管理 |
| 組織管理 |
部署(Composite)と社員(Leaf) |
サンプルコード
「ファイルとフォルダを同じ操作で扱う」ケースのソースコードです。
Component(共通インターフェース)
class FileSystemItem {
show(indent = 0) {
throw new Error("show()を実装してください");
}
}
Leaf(葉:実体のあるファイル)
class File extends FileSystemItem {
constructor(name) {
super();
this.name = name;
}
show(indent = 0) {
console.log(" ".repeat(indent) + "📄 " + this.name);
}
}
Composite(枝:フォルダ)
class Folder extends FileSystemItem {
constructor(name) {
super();
this.name = name;
this.children = [];
}
add(item) {
this.children.push(item);
}
show(indent = 0) {
console.log(" ".repeat(indent) + "📁 " + this.name);
for (const child of this.children) {
child.show(indent + 2);
}
}
}
実行例
const root = new Folder("root");
const src = new Folder("src");
const img = new Folder("images");
src.add(new File("index.js"));
src.add(new File("app.js"));
img.add(new File("logo.png"));
root.add(src);
root.add(img);
root.add(new File("README.md"));
root.show();
出力結果
📁 root
├ 📁 src
│├ 📄 index.js
│└ 📄 app.js
├ 📁 images
│└ 📄 logo.png
└ 📄 README.md
解説ポイント
File と Folder はどちらも 同じ型(FileSystemItem) を継承する。
同じ型にすることで、名称やアイコン保持などの属性を共通化することができます。
違いは、子階層の配列を持っているかどうか(または、fileとfolderなどのtypeを付与しておく)。
実際に使用する呼び出し側は、「ファイルかフォルダか」意識せずに操作できる。
属性判定のクラス(または関数)を作っておくだけで、判別も構造化できます。
再帰的に呼び出して、階層構造を簡潔に表現できる。
同列内のファイルやフォルダの検索などが便利に行えるのは、構造を理解するとわかりやすいですね。
メリット
・階層構造をシンプルに扱える(再帰処理が簡単)。
・「個」と「集合」を同一視でき、呼び出し側のロジックが統一される。
・新しい要素(ファイルタイプなど)を追加しやすい。
デメリット
・構造がやや抽象的になりすぎると理解しづらい。
・再帰処理の中でパフォーマンスが落ちる可能性(大量データ時)。
・ループ検出などを考慮しないと無限再帰になるリスク。
あとがき
ブランチ階層構造的に、親となるオブジェクトの内部に、子要素を配列で格納していき、ツリー構造モデルを構築するやり方です。
もっと他にもシンプルな書き方もできるかもしれませんが、オブジェクトデータで保持することで、拡張性などが高くなるので、GUI系で使えるパターンですね。
MVCパターンのモデル部分でこのデザインパターンを使うことで、運用効率がアップするイメージが持てました。
0 件のコメント:
コメントを投稿