「Composite」という英単語は、「合成物」を意味します。
このパターンを適用すると、「容器」と「中身」を同一視することができ、再帰的な構造の取扱いを容易にします。例えば、ファイルシステムで言うと、「容器」が「フォルダ」で、「中身」が「ファイル」「サブフォルダ」を意味します。同一視できるとは、対象となるオブジェクトが「容器」でも「中身」でも同じ様に取り扱える(同じ名前のメソッドで処理できる)ことを意味します。つまり、「Composite」パターンは階層構造で表現されるオブジェクトの取扱いを容易にするパターンです。
Compositeパターンのクラス図
1. Leaf.java
public class Leaf extends Component {
private String name;
private int value;
public Leaf(String name, int value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
protected int sumValue() {
System.out.println(" + " + value);
return value;
}
protected void printTree(String path) {
System.out.println(path + "-" + name);
}
}
2. Composite.java
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
public class Composite extends Component {
private String name;
private List<Component> components = new ArrayList<Component>();
public Composite(String name) {
this.name = name;
}
public String getName() {
return name;
}
protected void printTree(String path) {
System.out.println(path + "-" + name);
Iterator<Component> it = components.iterator();
while (it.hasNext()){
it.next().printTree(path + "-" + name);
}
}
protected int sumValue() {
int sum = 0;
Iterator<Component> it = components.iterator();
while (it.hasNext()){
sum += it.next().sumValue();
}
return sum;
}
public void add(Component component) throws ComponentAddException {
components.add(component);
}
}
3. Component.java
public abstract class Component {
public abstract String getName();
protected abstract int sumValue();
public void add(Component component) throws ComponentAddException {
/** この「add」メソッドはサブクラスで実装されない(「Leaf」)可能性があるため、
デフォルトの処理としては、例外を発生させるようにしておきます。 */
throw new ComponentAddException();
}
protected abstract void printTree(String path);
}
4. ComponentAddException.java
public class ComponentAddException extends Exception {
public ComponentAddException() {}
public ComponentAddException(String msg) {
super(msg);
}
}
5. Client.java
public class Client {
public static void main(String[] args) {
Composite comp1 = new Composite("A");
Composite comp11 = new Composite("AB");
Composite comp12 = new Composite("AC");
Composite comp13 = new Composite("AD");
Composite comp111 = new Composite("ABE");
Composite comp112 = new Composite("ABF");
try {
comp1.add(comp11);
comp1.add(comp12);
comp1.add(comp13);
comp11.add(comp111);
comp11.add(comp112);
comp11.add(new Leaf("a", 1));
comp11.add(new Leaf("b", 2));
comp11.add(new Leaf("c", 3));
comp13.add(new Leaf("d", 4));
comp112.add(new Leaf("e", 5));
int sum = comp1.sumValue();
System.out.println("----");
System.out.println(" " + sum);
System.out.println("");
comp1.printTree("");
} catch (ComponentAddException e) {
e.printStackTrace();
}
}
}
C:\sample\desin_pattern\composite>javac Client.java [Enter] C:\sample\desin_pattern\composite>java Client [Enter] + 5 + 1 + 2 + 3 + 4 ---- 15 -A -A-AB -A-AB-ABE -A-AB-ABF -A-AB-ABF-e -A-AB-a -A-AB-b -A-AB-c -A-AC -A-AD -A-AD-d