#はじめに
これは某社内で実施するデザインパターン勉強会で使用する資料です。
書籍「Java言語で学ぶデザインパターン」をベースに学習を進めますが、サンプルプログラムはC#に置き換えて解説します。
第1回:Iteratorパターン
第2回:Adapterパターン
第3回:Template Methodパターン
第4回:Factory Methodパターン
第5回:Singletonパターン
第6回:Prototypeパターン
第7回:Builderパターン
第8回:Abstract Factoryパターン
第9回:Bridgeパターン
第10回:Strategyパターン
#Compositeパターンとは
Compositeパターンは、容器と中身を同一視して、再帰的な構造を作るパターンです。
木構造をイメージするとわかりやすいかと思います。
サンプルプログラムでは、PC上でファイル管理するためにフォルダの階層を作成するのをイメージしてください。
##クラスの役割
クラス名 | 役割 |
---|---|
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