Compositeパターン
Compositeパターンは、容器と中身を同一視して、再帰的な構造を作るパターンです。
利用者は容器と中身を意識せずに使用することができます。
Compositeパターンを使用しない場合は、容器と中身を意識する必要がある。
コード例では、DirecotryクラスのListに追加したインスタンスがフォルダーなのか、ファイルなのか、判定する処理が発生します。
クラス図
クラス説明
クラス名 | クラス説明 |
---|---|
IEntry | FolderとFileを同一視するインターフェース |
Directory | フォルダークラス |
File | ファイルクラス |
Program | ユーザークラス |
実行イメージ [C#]
Composite.Directory : root
Composite.Directory : dir1
Composite.Directory : dir2
Composite.Directory : dir3
Composite.File : file4
Composite.File : file3
Composite.File : file1
Composite.File : file2
コード [C#]
using System;
using System.Collections.Generic;
namespace Composite
{
class Program
{
static void Main(string[] args)
{
Directory root = new Directory("root");
Directory dir1 = new Directory("dir1");
Directory dir2 = new Directory("dir2");
Directory dir3 = new Directory("dir3");
File file1 = new File("file1");
File file2 = new File("file2");
File file3 = new File("file3");
File file4 = new File("file4");
// フォルダーを追加する
root.AddEntry(dir1);
root.AddEntry(dir2);
dir2.AddEntry(dir3);
// ファイルを追加する
root.AddEntry(file1);
root.AddEntry(file2);
dir2.AddEntry(file3);
dir3.AddEntry(file4);
root.Output(0);
Console.ReadLine();
}
}
public interface IEntry
{
void Output(int someDepth);
}
public class Directory : IEntry
{
private string Name = null;
private List<IEntry> Entries = new List<IEntry>();
public Directory(string someName)
{
this.Name = someName;
}
public void AddEntry(IEntry someEntry)
{
Entries.Add(someEntry);
}
public void Output(int someDepth)
{
for (int i = 0; i < someDepth; i++)
{
Console.Write(" ");
}
Console.WriteLine("{0} : {1}", this.GetType().ToString(), this.Name);
foreach (var item in Entries)
{
// 階層を1つ深くする
item.Output(someDepth + 1);
}
}
}
public class File : IEntry
{
private string Name = null;
public File(string someName)
{
this.Name = someName;
}
public void Output(int someDepth)
{
for (int i = 0; i < someDepth; i++)
{
Console.Write(" ");
}
Console.WriteLine("{0} : {1}", this.GetType().ToString(), this.Name);
}
}
}
実行イメージ [C++]
[Pattern 1]
Direcotry : root
Direcotry : dir1
Direcotry : dir2
Direcotry : dir3
File : file4
File : file3
File : file1
File : file2
続行するには何かキーを押してください . . .
コード [C++]
#include <iostream>
#include <vector>
class IEntry
{
public:
virtual void Output(const int someDepth) = 0;
};
class Direcotry : public IEntry
{
private:
std::string mName;
std::vector<IEntry*> mList;
public:
Direcotry(std::string someName) : mName(someName) {}
public:
void AddEntry(IEntry* someEntry)
{
this->mList.emplace_back(someEntry);
}
void Output(const int someDepth)
{
for (int i = 0; i < someDepth; i++)
{
std::cout << " ";
}
std::cout << "Direcotry : " << this->mName.c_str() << std::endl;
for (IEntry* item : mList)
{
// 階層を1つ深くする
item->Output(someDepth + 1);
}
}
};
class File : public IEntry
{
private:
std::string mName;
public:
File(std::string someName) : mName(someName) {}
public:
void Output(const int someDepth)
{
for (int i = 0; i < someDepth; i++)
{
std::cout << " ";
}
std::cout << "File : " << this->mName.c_str() << std::endl;
}
};
int main()
{
std::cout << "[Pattern 1]" << std::endl;
Direcotry root("root");
Direcotry dir1("dir1");
Direcotry dir2("dir2");
Direcotry dir3("dir3");
File file1("file1");
File file2("file2");
File file3("file3");
File file4("file4");
// フォルダーを追加する
root.AddEntry(&dir1);
root.AddEntry(&dir2);
dir2.AddEntry(&dir3);
// ファイルを追加する
root.AddEntry(&file1);
root.AddEntry(&file2);
dir2.AddEntry(&file3);
dir3.AddEntry(&file4);
root.Output(0);
system("pause");
}