容器と中身を同一視することにより、再帰的に扱えるようにする。
一番分かりやすい例としてはファイルシステムだろう。ファイルとディレクトリを共通のインタフェースを持つ親クラスから派生するようにする。そうすればディレクトリの中にさらにディレクトリがあっても、ファイルがあっても同じように扱うことができるし、再帰的にディレクトリの中を検索していくことができる。
その他、ウィンドウシステムも同じように考えることができる。あるウィンドウの中に項目があり、その項目を選択するとさらに別のウィンドウが開くように。
Menu.java
public abstract class Menu { public abstract String getName(); public Menu add(Menu menu) { return this; } public void disp() { disp(""); } protected abstract void disp(String prefix); }
Window.java
import java.util.Vector; import java.util.Iterator; public class Window extends Menu { private String name; private Vector menus = new Vector(); public Window(String name) { this.name = name; } public String getName() { return name; } public Menu add(Menu menu) { menus.add(menu); return this; } public void disp(String prefix) { System.out.println( prefix + getName() ); Iterator it = menus.iterator(); while(it.hasNext()) { Menu menu = (Menu)it.next(); menu.disp( prefix + " " ); } } }
Item.java
public class Item extends Menu { private String name; public Item(String name) { this.name = name; } public String getName() { return name; } public void disp(String prefix ) { System.out.println( prefix + getName() ); } }
Main.java
public class Main { public static void main(String[] args) { Window topwindow = new Window("Top"); Window usewindow = new Window("Use"); Item status = new Item("Status"); topwindow.add(usewindow); topwindow.add(status); Item money = new Item("Money"); Item weapon = new Item("Weapon"); usewindow.add(money); usewindow.add(weapon); topwindow.disp(); } }
実行結果
Top Use Money Weapon Status
このプログラム例は、トップメニューのウィンドウがあり、その中にはUseコマンドとStatusコマンドがある。Useコマンドは子ウィンドウになっており、MoneyコマンドとWeaponコマンドがある。
注意しなければならないのは、ちゃんと木構造になるようにすること。もし、親子構造が循環してしまうと無限ループになってしまう。
参考文献:Java言語で学ぶデザインパターン入門
参考:
ギコ猫とCompositeパターン
Composite パターン - Wikipedia