オブジェクト指向設計


Composite パターン - コンポジットパターン

2008/06/13 21:29Update
TAGS: Composite | GoF | デザインパターン | OOD | オブジェクト指向設計

Composite パターンはGoFによる23種類のデザインパターンの構造に関連するパターンです。Composite パターンでは、「ツリーのような再帰的なデータ構造」を同一インタフェースで扱えることができます。

はじめに


ツリーのような「枝」と「葉」を持つデータ構造は少なくがありません。次は、再帰的な構造であるファイルシステムの例です。
C:\
|
+---Windows
|          |
|          + AppPatch
|                    |
|                    + AcLayers.dll
|          + Config
|                 |
|                 + somefile1.txt
|                 + somefile2.txt
+---MyWorks
|          |
|          + Folder001
|                    |
|                    + AcLayers.dll
|          + Folder002
|                    |
|                    + somefile1.txt
|                    + somefile2.txt
...

フォルダの中にファイル(葉)を存在したり、サブフォルダ(枝)を存在したり、さらにサブフォルダの中にもファイルやフォルダを存在したり・・・

Composite パターンは、このようなデータ構造を同一インタフェースで処理することによって、容易に扱えるようになります。
Composite パターンを使えば、「枝」であろうか、「葉」であろうか、関係なく同じインタフェースで取り扱いを行うことができます。

Composite パターンの使用シーン


◇ 再帰的なデータ構造の取り扱いが必要
◇ 取り扱いをより簡単な方法で行いたい

Composite パターンのクラス図


<<クラス図>>


Component:再帰的なデータ構造の抽象。次のような機能を提供する。
- 本来のインタフェースの定義
- 子データセットの管理(追加、削除、アクセス)
- 親データへのリンク(オプション)
Leaf:「葉」クラス。Componentから継承。
Composite:「枝」クラス。Componentから継承。

Composite パターンの使用例



Composite パターンは実装は次の通りです。
1、Component抽象クラスを定義します
2、Leaf(葉)クラスを定義します
3、Composite(枝)クラスを定義します


先ほど述べたファイルシステムの例をComposite パターンで実装してみたいと思います。
※以下はJava言語による実装です。ほかの言語も同じような考え方です。

import java.util.ArrayList;
import java.util.List;


//Component抽象クラスに相当する IFile.java
interface IFile {
    public void printName();
    
    //子供追加
    public boolean addChild(IFile file);
    //子供削除
    public boolean removeChild(IFile file);
    //子供取得
    public List<IFile> getChildren();
}

//Leaf(葉)クラスに相当する File.java
class File implements IFile {
    private String name;
    
    public File(String name) {
        this.name = name;
    }
    public void printName() {
        System.out.println(name);
    }

    //子供はないので、空実装
    public boolean addChild(IFile file) {
        return false;
    }

    //子供はないので、空実装
    public boolean removeChild(IFile file) {
        return false;
    }

    //子供はないので、空実装
    public List<IFile> getChildren() {
        return null;
    }
    
}

//Composite(枝)クラスに相当する Folder
class Folder implements IFile {
    private String name;
    private List <IFile> childList;
    
    public Folder(String name) {
        this.name = name;
        this.childList = new ArrayList<IFile>();
    }
    public void printName() {
        System.out.println(name);
    }

    //子供追加
    public boolean addChild(IFile file) {
        return childList.add(file);
    }

    //子供削除
    public boolean removeChild(IFile file) {
        return childList.remove(file);
    }

    //子供取得
    public List<IFile> getChildren() {
        return childList;
    }
}


そして、使い方は
import java.util.ArrayList;
import java.util.List;

public class Client {
    public static void main(String[] args) {
        
        //再帰的なデータ構造を構築
        Folder rootFolder = new Folder("c:\\");
        Folder compositeFolder = new Folder("composite");
        rootFolder.addChild(compositeFolder);
        Folder windowsFolder = new Folder("windows");
        rootFolder.addChild(windowsFolder);
        File file = new File("TestComposite.java");
        compositeFolder.addChild(file);
        
        //再帰的なデータ構造をアクセス
        printTree(rootFolder);
    }
    
    private static void printTree(IFile ifile) {
        ifile.printName();
        List <IFile> children = ifile.getChildren();
        
        for (IFile file:children) {
            if (file instanceof File) {
                System.out.print("  ");
                file.printName();
            } else if (file instanceof Folder) {
                printTree(file);    //再帰
            }
        }
    }
}


実行結果は以下になります。

C:\Composite>javac *.java
C:\Composite>java Client
c:\
composite
  TestComposite.java
windows
C:\Composite>

有关作者
Syboos.jp編集長AJavaやオープンソース情報の執筆、Webサイトの開発や運営全般の業務に携わる。

Sponsored Link


Comments