1. 程式人生 > >c++ 設計模式之原型模式

c++ 設計模式之原型模式

按照設計模式書上的介紹:

意圖:

       用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。

適用性:

        當一個系統應該獨立於他的產品建立、構成和表示時,需要使用原型模式

        當要例項化的類是在執行時刻指定時,如通過動態裝載

        為了避免建立一個與產品類層次平行的工廠類層次時

        當一個類的例項只能有幾個不同狀態組合中的一種時,建立相應數目的原型並克隆他們可能比每次用合適的狀態手工例項化該類更方便一些。

我們先給一個通用的架構例子:

prototype.h

//設計模式之原型模式

/*
解析:
Prototype模式其實就是常說的"虛擬建構函式"一個實現,C++的實現機制中並沒有支援這個特性,
但是通過不同派生類實現的Clone介面函式可以完成與"虛擬建構函式"同樣的效果.舉一個例子來
解釋這個模式的作用,假設有一家店鋪是配鑰匙的,他對外提供配製鑰匙的服務(提供Clone介面函
數),你需要配什麼鑰匙它不知道只是提供這種服務,具體需要配什麼鑰匙只有到了真正看到鑰匙
的原型才能配好.也就是說,需要一個提供這個服務的物件,同時還需要一個原型(Prototype),不
然不知道該配什麼樣的鑰匙.

*/
//宣告一個虛擬基類,所有的原型都從這個基類繼承,
class prototype
{
public:
	prototype(){}
	virtual ~prototype(){}
	virtual prototype* clone() = 0;//純虛擬函式,需要供繼承者自行實現
};

// 派生自Prototype,實現Clone方法
class concreateprototype1:public prototype
{
public:
	concreateprototype1();
	concreateprototype1(const concreateprototype1&);
	virtual ~concreateprototype1();
	virtual prototype* clone();
};

// 派生自Prototype,實現Clone方法
class concreateprototype2:public prototype
{
public:
	concreateprototype2();
	concreateprototype2(const concreateprototype2&);
	virtual ~concreateprototype2();
	virtual prototype* clone();
};


prototype.cpp

#include "prototype.h"
#include <iostream>
using namespace std;
concreateprototype1::concreateprototype1()
{
	cout<<"concreteprototype1 create"<<endl;
}

concreateprototype1::concreateprototype1(const concreateprototype1 &contype )
{
	cout<<"copy the concreteprototype1"<<endl;
}
concreateprototype1::~concreateprototype1()
{
	cout<<"destruction of concreteprototype1"<<endl;
}
prototype* concreateprototype1::clone()
{
	return new concreateprototype1(*this);
}

concreateprototype2::concreateprototype2()
{
	cout<<"concreteprototype2 create"<<endl;
}

concreateprototype2::concreateprototype2(const concreateprototype2 &contype )
{
	cout<<"copy the concreteprototype2"<<endl;
}
concreateprototype2::~concreateprototype2()
{
	cout<<"destruction of concreteprototype2"<<endl;
}
prototype* concreateprototype2::clone()
{
	return new concreateprototype2(*this);
}

使用的時候可以這麼使用:

	prototype *ptype1 = new concreateprototype1();
	prototype *copytype1 = ptype1->clone();

	delete ptype1;
	delete copytype1;

找工作的時候,我們需要準備簡歷。假設沒有列印裝置,因此需手寫簡歷,這些簡歷的內容都是一樣的。這樣有個缺陷,如果要修改簡歷中的某項,那麼所有已寫好的簡歷都要修改,工作量很大。隨著科技的進步,出現了列印裝置。我們只需手寫一份,然後利用列印裝置影印多份即可。如果要修改簡歷中的某項,那麼修改原始的版本就可以了,然後再影印。原始的那份手寫稿相當於是一個原型,有了它,就可以通過影印(拷貝)創造出更多的新簡歷。

resume.h

//首先抽象一個基類
class resume
{
protected:
	char *name;
public:
	resume()
	{

	}
	virtual ~resume()
	{

	}

	virtual void set(const char *str)
	{

	}
	virtual void show()
	{

	}
	virtual resume* clone()
	{
		return 0;
	}
};

class ResumeA : public resume
{
public:
	ResumeA(const char *str);  //建構函式
	ResumeA(const ResumeA &r); //拷貝建構函式
	~ResumeA();                //解構函式
	ResumeA* clone();          //克隆,關鍵所在
	void show();               //顯示內容
};


class ResumeB : public resume
{
public:
	ResumeB(const char *str);  //建構函式
	ResumeB(const ResumeB &r); //拷貝建構函式
	~ResumeB();                //解構函式
	ResumeB* clone();          //克隆,關鍵所在
	void show();               //顯示內容
};


resume.cpp

#include "resume.h"
#include <iostream>
using namespace std;
ResumeA::ResumeA(const char *str) 
{
	if(str == NULL) {
		name = new char[1]; 
		name[0] = '\0'; 
	}
	else {
		name = new char[strlen(str)+1];
		strcpy(name, str);
	}
}
ResumeA::~ResumeA() { delete [] name;}
ResumeA::ResumeA(const ResumeA &r) {
	name = new char[strlen(r.name)+1];
	strcpy(name, r.name);
}
ResumeA* ResumeA::clone() {
	return new ResumeA(*this);
}
void ResumeA::show() {
	cout<<"ResumeA name : "<<name<<endl; 
}

ResumeB::ResumeB(const char *str) 
{
	if(str == NULL) {
		name = new char[1]; 
		name[0] = '\0'; 
	}
	else {
		name = new char[strlen(str)+1];
		strcpy(name, str);
	}
}
ResumeB::~ResumeB() { delete [] name;}
ResumeB::ResumeB(const ResumeB &r) {
	name = new char[strlen(r.name)+1];
	strcpy(name, r.name);
}
ResumeB* ResumeB::clone() {
	return new ResumeB(*this);
}
void ResumeB::show() {
	cout<<"ResumeB name : "<<name<<endl; 
}

int main()
{
	resume *r1 = new ResumeA("A");
	resume *r2 = new ResumeB("B");
	resume *r3 = r1->clone();
	resume *r4 = r2->clone();
	r1->show();
	r2->show();
	//刪除r1,r2
	delete r1;
	delete r2;	
	r1 = r2 = NULL;
	//深拷貝所以對r3,r4無影響
	r3->show(); 
	r4->show();
	delete r3; delete r4;
	r3 = r4 = NULL;

}


其實這個設計模式比較簡單,我們總結一下具體操作步驟。

1、宣告一個抽象基類,並定義clone()函式為純虛擬函式。

2、例項化各個子類,並且實現複製建構函式,並實現clone()函式