Prototype パターン

Prototype pattern - Wikipedia

クラスからオブジェクトではなく、オブジェクトからオブジェクトを生成するパターン。Product(Prototype)だけを扱うManager(Client)が、UnderlinePen(Concrete Protype)を知ることなく新たなオブジェクトを生成することができるのがいい。ClientがProtypeの実装に束縛されないということ。

#include<iostream>
#include<string>
#include<map>
using namespace std;
//Prototype
class Product
{
public :
	virtual void Use(string str) = 0;
	virtual Product* CreateClone() = 0;
};
//Concrete Prototype 1
class UnderlinePen : public Product
{
public :
	UnderlinePen(char chr){
		this->under_line_ = chr;
	}
	UnderlinePen(const UnderlinePen & p) : under_line_(p.under_line_){
	}
	void Use(string str){
		cout << "$" << str.c_str() << "$" << endl << " ";
		for(unsigned int i = 0; i < str.length(); i++){
			cout << under_line_;
		}
		cout << endl;
	}
	Product * CreateClone(){
		return new UnderlinePen(*this);
	}
private :
	char under_line_;
};
//Concrete Prototype 2
class MessageBox : public Product
{
public :
	MessageBox(char chr){
		this->deco_character_ = chr;
	}
	MessageBox(const MessageBox & p) : deco_character_(p.deco_character_){
	}
	void Use(string str){
		for(unsigned int i = 0; i < (str.length()+2); i++){
			cout << deco_character_;
		}
		cout << endl;
		cout << deco_character_ << str.c_str() << deco_character_ ;
		cout << endl;
		for(unsigned int i = 0; i < (str.length()+2); i++){
			cout << deco_character_;
		}
		cout << endl;
	}
	Product * CreateClone(){
		return new MessageBox(*this);
	}
private :
	char deco_character_;
};
//Client
class Manager
{
public :
	Product * Create(string key){
		return((this->items_[key])->CreateClone());
	}
	void Register(string key, Product *p){
		items_[key] = p;
	}
	~Manager(){
		map<string, Product*>::iterator it = items_.begin();
		while(it != items_.end()){
			delete (*it).second;
			++it;
		}
	}
private : 
	map<string, Product*> items_;
};
int main()
{
	Manager *manager = new Manager();
	manager->Register("strong message", new UnderlinePen('~'));
	manager->Register("deco"          , new MessageBox('='));
	manager->Register("signature"     , new MessageBox('*'));
	Product *p1 = manager->Create("strong message");
	Product *p2 = manager->Create("deco");
	Product *p3 = manager->Create("signature");
	p1->Use("Hello, world.");
	p2->Use("Hello, world.");
	p3->Use("Hello, world.");

	delete manager;
	delete p1;
	delete p2;
	delete p3;
    return 0;
}