技術とか戦略とか

IT技術者が技術や戦略について書くブログです。

javaでのCompositeパターン

Compositeパターンは、入れ物のクラスと中身のクラスを1つの抽象クラスでまとめ、同一視できるようにするパターンです。
このパターンを取り入れることで、クラスを使う側から見て入れ物のクラスなのか中身のクラスなのかを意識する必要がなくなります。
 
ファイルシステムの例が多いですが、理解を深めるために今回はあえて別の例を出して説明します。
袋と本・ゲームソフトの例を出して説明します。
単に袋の中に本やゲームソフトを入れるだけでなく、袋が破れないように袋を二重にする(袋の中に袋を入れる)こともありますし、袋の中に本用の袋とゲームソフト用の袋を入れて分類することもあります。
このような場合、Compositeパターンを用いることで、袋でも本・ゲームソフトでも同じように処理することができるようになります。
 
【サンプルコード】
・Entry.java
public abstract class Entry {

    public abstract void descript();

}
 
・Book.java
public class Book extends Entry {

    private String name;

    public Book(String name) {
        this.name = name;
    }

    public void descript() {
        System.out.println("これは" + name + "という本です。");
    }
}
 
・GameSoft.java
public class GameSoft extends Entry {

    private String name;

    public GameSoft(String name) {
        this.name = name;
    }

    public void descript() {
        System.out.println("これは" + name + "というソフトです。");
    }
}
 
・Bag.java
import java.util.ArrayList;
import java.util.Iterator;

public class Bag extends Entry {

    private String name;
    private ArrayList<Entry> item = new ArrayList<Entry>();

    public Bag(String name) {
        this.name = name;
    }

    public Entry add(Entry entry) {
        item.add(entry);
        return this;
    }

    public void descript() {
        System.out.println("これは" + name + "という袋です。");
        Iterator<Entry> iterator = item.iterator();
        while (iterator.hasNext()) {
            Entry entry = (Entry) iterator.next();
            System.out.print("袋「" + name + "」の中身:");
            entry.descript();
        }
    }
}
 
・EntryMain.java
public class EntryMain {

    public static void main(String[] args) {

        // 袋、本・ゲームソフトを作成
        Bag bigBag = new Bag("BigBag");
        Bag emptyBag = new Bag("EmptyBag");
        Bag bagOfBook = new Bag("BagOfBook");
        Bag bagOfSoft = new Bag("BagOfSoft");
        Book bigBook = new Book("BigBook");
        Book book1 = new Book("Book1");
        Book book2 = new Book("Book2");
        GameSoft soft1 = new GameSoft("Soft1");
        GameSoft soft2 = new GameSoft("Soft2");

        // 袋の中に詰める
        // 袋の中に詰めるのは袋でも本・ゲームソフトでも良い
        // (入れ物のクラスなのか中身のクラスなのか意識しなくて良い)
        bagOfBook.add(book1);
        bagOfBook.add(book2);
        bagOfSoft.add(soft1);
        bagOfSoft.add(soft2);
        bigBag.add(emptyBag);
        bigBag.add(bagOfBook);
        bigBag.add(bagOfSoft);
        bigBag.add(bigBook);

        // 説明を見る
        // 袋でも本・ゲームソフトでも同じように説明を見ることができる
        // (入れ物のクラスなのか中身のクラスなのか意識しなくて良い)
        System.out.println("[BigBag(入れ物クラス)の説明]");
        bigBag.descript();
        System.out.println();
        System.out.println("[Book1(中身クラス)の説明]");
        book1.descript();

    }
}
 
【実行結果】
[BigBag(入れ物クラス)の説明]
これはBigBagという袋です。
袋「BigBag」の中身:これはEmptyBagという袋です。
袋「BigBag」の中身:これはBagOfBookという袋です。
袋「BagOfBook」の中身:これはBook1という本です。
袋「BagOfBook」の中身:これはBook2という本です。
袋「BigBag」の中身:これはBagOfSoftという袋です。
袋「BagOfSoft」の中身:これはSoft1というソフトです。
袋「BagOfSoft」の中身:これはSoft2というソフトです。
袋「BigBag」の中身:これはBigBookという本です。

[Book1(中身クラス)の説明]
これはBook1という本です。