デザインパターン勉強会　第11回：Compositeパターン

#はじめに
これは某社内で実施するデザインパターン勉強会で使用する資料です。
書籍「[Java言語で学ぶデザインパターン](http://www.hyuki.com/dp/)」をベースに学習を進めますが、サンプルプログラムはC＃に置き換えて解説します。

第1回：[Iteratorパターン](http://qiita.com/Nuits/items/800f080d44b52e1cae18)
第2回：[Adapterパターン](https://qiita.com/Nanakusajp/items/747d1913b1e8bea8d340)
第3回：[Template Methodパターン](http://qiita.com/_kyam/items/9b5722e6a9635af6e18b)
第4回：[Factory Methodパターン](https://qiita.com/ayayo/items/3eece04bbc4b7504179a)
第5回：[Singletonパターン](https://qiita.com/Keenag/items/cae53d55cb953562fee4)
第6回：[Prototypeパターン](https://qiita.com/aconit96/items/9235d30a07f508886c7e)
第7回：[Builderパターン](https://qiita.com/Uesk/items/8f12be304671e9905795)
第8回：[Abstract Factoryパターン](https://qiita.com/buru/items/bb3930dda1bdd2b5f70b)
第9回：[Bridgeパターン](https://qiita.com/mitakaosamu/items/cff9a39953ae03092f43)
第10回：[Strategyパターン](https://qiita.com/a1146234/items/fdecc374b7225d99ab07)

---
#Compositeパターンとは
Compositeパターンは、容器と中身を同一視して、再帰的な構造を作るパターンです。
木構造をイメージするとわかりやすいかと思います。

サンプルプログラムでは、PC上でファイル管理するためにフォルダの階層を作成するのをイメージしてください。

---
#サンプルプログラム
##クラス図
![image.png](https://qiita-image-store.s3.amazonaws.com/0/193740/b678b086-4158-51ab-026e-b360ed123b4f.png)

---

##クラスの役割

| クラス名 | 役割 |
|:--|:--|
| IEntry | FolderとFileを同一視するインターフェース |
| Folder | フォルダを表すクラス |
| File | ファイルを表すクラス |
| Program | 動作確認用のクラス |

---  
##IEntry
IEntryは、FolderクラスとFileクラスの構成を指定するためのインターフェースです。
・出力の処理を指定するOutput
で構成されています

```
    interface IEntry
    {
        void Output(int depth);
    }
```

---  
##Folder
Folderクラスはフォルダを表現しているクラスです
インターフェースの実装の他に、
フォルダ名を格納するnameフィールド
自身より下層のフォルダやファイルを持つentriesフィールドを持っています。

Outputメソッドでは、自身のNameを出力した後に自身より下層の要素のOutputメソッドを実行しています

```
    class Folder : IEntry
    {
        private string name;
        private List<IEntry> entries = new List<IEntry>();

        public Folder(string name)
        {
            this.name = name;
        }

        public void Output(int depth)
        {
            for(int i=0; i < depth; i++)
            {
                Console.Write("  ");
            }
            Console.WriteLine("Folder:"+name);
            foreach(IEntry entry in entries){
                entry.Output(depth+1);
            }

        }

        public void AddEntry(IEntry entry)
        {
            entries.Add(entry);
        }
    }
```
---  
##File
Fileクラスはファイルを表現しているクラスです
インターフェースで指定されたメソッドの他に
自身のファイル名を格納するNameフィールドを持っています。

```
    class File : IEntry
    {
        private string name;

        public File(string name)
        {
            this.name = name;
        }

        public void Output(int depth)
        {
            for (int i = 0; i < depth; i++)
            {
                Console.Write("  ");
            }
            Console.WriteLine("File:" + name);
        }
        
    }
```

---  
##Program

ファイルとフォルダのインスタンスを作成し、フォルダに追加します
追加する要素がファイルかフォルダかを意識せずに追加できます

```
    class Program
    {
        static void Main(string[] args)
        {
            var root = new Folder("root");
            var user = new Folder("user");
            var temp = new Folder("temp");
            var documents = new Folder("document");
            var game = new Folder("げぇむ");

            var gomi = new File("ごみ");
            var ika = new File("ika");
            var tako = new File("tako");
            var salmon = new File("salmon");

            //フォルダを追加
            root.AddEntry(user);
            root.AddEntry(temp);
            user.AddEntry(documents);
            user.AddEntry(game);

            //ファイルを追加
            temp.AddEntry(gomi);
            game.AddEntry(ika);
            game.AddEntry(tako);
            game.AddEntry(salmon);

            root.Output(0);

        }
    }
```

---
##Program実行結果
```
Folder:root
  Folder:user
    Folder:document
    Folder:げぇむ
      File:ika
      File:tako
      File:salmon
  Folder:temp
    File:ごみ
```
---

#まとめ
- Compositeパターンは、容器と中身を同一視して、再帰的な構造を作るパターンです
- 利用者は容器と中身を意識せずに使用することができます
- ただし、利用できないメソッドがある場合は気をつける必要があります

---
#サンプルコード
サンプルコードは以下で公開しています
https://github.com/Nanakusajp/CompositePattern