Composite パターン(コンポジット・パターン)とは、GoF (Gang of Four; 4人のギャングたち) によって定義されたデザインパターンの1つである。「構造に関するパターン」に属する。Composite パターンを用いるとディレクトリとファイルなどのような、木構造を伴う再帰的なデータ構造を表すことができる。
Composite パターンにおいて登場するオブジェクトは、「枝」と「葉」であり、これらは共通のインターフェースを実装している。そのため、枝と葉を同様に扱えるというメリットがある。 Composite パターンのクラス図を以下に挙げる。 Composite パターンを用いてディレクトリ構造を表すJavaプログラムの例を示す。このプログラムは、 から構成される。 import java.util.ArrayList; import java.util.List; interface FileInterface { public void defaultMethod(int depth); public List<FileInterface> getChildren(); public boolean addComponent(FileInterface c); public boolean removeComponent(FileInterface c); } class File implements FileInterface { private String name; public File(String name) { this.name = name; } public void defaultMethod(int depth) { for (int i = 0; i < depth; i++) System.out.print(" "); System.out.println("file:" + this.name); } public List<FileInterface> getChildren() { return null; } public boolean addComponent(FileInterface c) { return false; } public boolean removeComponent(FileInterface c) { return false; } } class Folder implements FileInterface { private String name; private List<FileInterface> fileList = new ArrayList<FileInterface>(); public Folder(String name) { this.name = name; } public void defaultMethod(int depth) { for (int i = 0; i < depth; i++) System.out.print(" "); System.out.println("folder:" + name); for (FileInterface file : fileList) { file.defaultMethod(depth + 1); } } public List<FileInterface> getChildren() { return this.fileList; } public boolean addComponent(FileInterface c) { return this.fileList.add(c); } public boolean removeComponent(FileInterface c) { return this.fileList.remove(c); } } public class DirectoryUser { public static void main(String [] args){ FileInterface root = new Folder("root"); FileInterface usr = new Folder("usr"); FileInterface var = new Folder("var"); FileInterface home = new Folder("home"); FileInterface user1 = new Folder("user1"); FileInterface file1 = new File("file1"); root.addComponent(usr); usr.addComponent(var); root.addComponent(home); home.addComponent(user1); user1.addComponent(file1); root.defaultMethod(0); } } 実行結果folder:root folder:usr folder:var folder:home folder:user1 file:file1 Composite パターンを用いる際には、データ構造がきちんと木構造を保つようにしなければならない。親子関係が循環してしまった場合、Component#operation()を実行した際に無限ループに陥るからである。 例えば、利用例のソースコードを書き換えた以下のプログラムは、処理が dir1.defaultMethod(0); の行に達した時に、無限に出力し続けてしまう。 public class LoopExample { public static void main(String [] args){ FileInterface dir1 = new Folder("dir1"); FileInterface dir2 = new Folder("dir2"); FileInterface dir3 = new Folder("dir3"); dir1.addComponent(dir2); dir2.addComponent(dir3); dir3.addComponent(dir1); dir1.defaultMethod(0); } }
クラス図
利用例
枝を表すクラス : Folderクラス
葉を表すクラス : Fileクラス
共通インタフェース : FileInterfaceインタフェース
実行例を示すためのクラス : DirectoryUserクラス
注意事項自分自身を参照している例循環している例
関係するパターン
Interpreter パターン
文法表現が Composite パターンとなる場合が多い。
関連項目
木構造 (データ構造)
再帰データ型
再帰呼び出し
無限ループ
表
話
編
歴
生成に関するパターン
Abstract factory
Builder
Factory method
Prototype
Singleton
構造に関するパターン
Adapter
Bridge
Composite
Decorator
Facade
Flyweight
Proxy
振る舞いに関するパターン
Chain of responsibility
Command
Interpreter
Iterator
Mediator
Memento
Observer
State
Strategy
Template method
Visitor
並行性に関するパターン
Active object(英語版)
Balking(英語版)
Double-checked locking(英語版)
Event-based asynchronous(英語版)
Guarded suspension(英語版)
Join(英語版)
ロック
モニタ
Proactor(英語版)
Reactor
Readers?writer lock(英語版)
Scheduler(英語版)
Thread pool(英語版)
スレッド局所記憶
アーキテクチャに関するパターン
Front Controller(英語版)
Interceptor(英語版)
MVC
MVVM
多層アーキテクチャ
Specification(英語版)
出版-購読型モデル
Naked objects(英語版)
Service Locator(英語版)
Active Record
Identity map(英語版)
Data Access Object
Data Transfer Object
その他のパターン
依存性の注入 (DI)
遅延読み込み
モックオブジェクト
Null object(英語版)
Object pool(英語版)
Servant(英語版)
Type tunnel(英語版)
関連する人々
ギャング・オブ・フォー
エーリヒ・ガンマ
リチャード・ヘルム
ラルフ・ジョンソン
ジョン・ブリシディース
クリストファー・アレグザンダー
グラディ・ブーチ
ケント・ベック
ウォード・カニンガム
マーティン・ファウラー
ロバート・セシル・マーティン(英語版)
ジム・コプリエン(英語版)
ダグラス・C. シュミット(英語版)
リンダ・ライジング(英語版)
関連項目
アナリシスパターン
アンチパターン