のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

DesignPattern Composite(再帰処理)

Sponsored Links

皆さんこんにちは
お元気ですか?私はふるふるしてます。お酒がきついー

さて今日、DesignPatternのCompositeです。

CompistePatternとは

「容器と中身を同一視すること」とのことです。実装上では容器と中身のメソッドを統一し、
容器の中に更に容器があるような再帰的な構造を取り扱うようにできます。

フォルダシステムとかはいい例ですね。

クラス図

f:id:tereka:20140628120946p:plain

#include <iostream>
#include <vector>
#include <string>
#include <sstream> 

using namespace std;

//Entryの
class Entry{
public:
	string file_name;
	virtual void print() = 0;
};

//フォルダー
class Folder:public Entry{
	vector<Entry*> files;
public:
	Folder(string &name);
	void add(Entry *entry);
	virtual void print();
};

Folder::Folder(string &name){
	file_name = name;
}

void Folder::add(Entry *entry){
	files.push_back(entry);
}

void Folder::print(){
	cout << file_name << endl;
	cout << "展開開始" << endl;
	for(auto entry:files){
		entry->print();
	}
	cout << "展開終了" << endl;
}

//ファイル
class File:public Entry{
public:
	File(string &name);
	virtual void print();
};

File::File(string &name){
	file_name = name;
}

void File::print(){
	cout << file_name << endl;
}

//リンク
class SymbolicLink:public Entry{
public:
	SymbolicLink(string &name);
	virtual void print();	
};

SymbolicLink::SymbolicLink(string &name){
	file_name = name;
}

void SymbolicLink::print(){
	cout << file_name << endl;
}

template<typename T>
string toString(T a){
	stringstream ss;
	ss << a;
	return ss.str();
}

int main(int argc, char const *argv[]){
	string foldername = "folder";
	Folder *folder = new Folder(foldername);
	foldername = "folder2";
	Folder *folder2 = new Folder(foldername);

	string filename = "file";
	string symboliclink = "symbolicLink";

	for(int i = 0; i < 3; i++){
		string s_filename = filename + toString(i);
		string s_symbolicname = symboliclink + toString(i);

		File *file = new File(s_filename);
		SymbolicLink *link = new SymbolicLink(s_symbolicname);

		folder->add(file);
		folder->add(link);
	}
	folder->add(folder2);

	filename = "file2_";
	symboliclink = "symbolicLink2_";

	for(int i = 0; i < 3; i++){
		string s_filename = filename + toString(i);
		string s_symbolicname = symboliclink + toString(i);

		File *file = new File(s_filename);
		SymbolicLink *link = new SymbolicLink(s_symbolicname);

		folder2->add(file);
		folder2->add(link);
	}

	folder->print();

	return 0;
}

Entry classを生成し、容器であるFolder、中身であるFileとSymbolicLink全てに継承させ、同じメソッドをもたせます。
そして、一番上の構造のFolderでprintを実行することによって全てのプログラムを実行をしています。