Design Pattern | Composite Pattern(コンポジットパターン)
Compositeパターンとは?
- Compositeという単語は混合または複合という意味である。
- Compositeパターンは、容器と中身を同一視して再帰的な構造を作る方式である。
- ディレクトリとファイルを一緒にディレクトリエントリとして扱うために、コンテナと中身を同じ種類のものとして扱うと便利な場合がある。例えば、容器の中には中身を入れてもよく、さらに容器を入れてもよい。このように再帰構造を作ることができる。
- GoFデザインパターンでは、構造に関するデザインパターンに分類される。
Compositeパターンのサンプルプログラム
ディレクトリ、ファイル一覧を表示するサンプルプログラムである。
Class Diagram

1. Entryクラス
FileとDirectoryの基本となるクラスである。
Entry.java
package com.devkuma.designpattern.structural.composite;
public abstract class Entry {
public abstract String getName();
protected abstract void printList(String prefix);
public void printList() {
printList("");
}
}
2. Fileクラス
ファイルを表すクラスである。
File.java
package com.devkuma.designpattern.structural.composite;
public class File extends Entry {
private String name;
public File(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
protected void printList(String prefix) {
System.out.println(prefix + "/" + name);
}
}
3. Directoryクラス
ディレクトリを表すクラスである。
Directory.java
package com.devkuma.designpattern.structural.composite;
import java.util.ArrayList;
import java.util.Iterator;
public class Directory extends Entry {
private String name;
private ArrayList<Entry> directory = new ArrayList();
public Directory(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
public Entry add(Entry entry) {
directory.add(entry);
return this;
}
@Override
protected void printList(String prefix) {
System.out.println(prefix + "/" + name);
Iterator<Entry> it = directory.iterator();
while (it.hasNext()) {
Entry entry = it.next();
entry.printList(prefix + "/" + name);
}
}
}
4. Mainクラス
メイン処理を実行するクラスである。
Main.java
package com.devkuma.designpattern.structural.composite;
public class Main {
public static void main(String[] args) {
Directory workspaceDir = new Directory("workspace");
Directory compositeDir = new Directory("composite");
Directory testDir1 = new Directory("test1");
Directory testDir2 = new Directory("test2");
workspaceDir.add(compositeDir);
workspaceDir.add(testDir1);
workspaceDir.add(testDir2);
File directory = new File("Directory.java");
File entity = new File("Entity.java");
File file = new File("file.java");
File main = new File("main.java");
compositeDir.add(directory);
compositeDir.add(entity);
compositeDir.add(file);
compositeDir.add(main);
workspaceDir.printList();
}
}
5. 実行結果
/workspace
/workspace/composite
/workspace/composite/Directory.java
/workspace/composite/Entity.java
/workspace/composite/file.java
/workspace/composite/main.java
/workspace/test1
/workspace/test2
メリット
すべてのオブジェクト(File、Directory)は共通の抽象クラスを持つため、クライアントから見たとき、それがFileなのかDirectoryなのか、中身を意識する必要がなく、同じように扱える。
また、新しいクラス(例: SymbolicLink)を追加しても、基本クラス(Entry)のインターフェースが変わらなければ、クライアントの処理には影響しない。