按照設計模式書上的介紹:
意圖:
用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。
適用性:
當一個系統應該獨立於他的產品創建、構成和表示時,需要使用原型模式
當要實例化的類是在運行時刻指定時,如通過動態裝載
為了避免創建一個與產品類層次平行的工廠類層次時
當一個類的實例只能有幾個不同狀態組合中的一種時,建立相應數目的原型並克隆他們可能比每次用合適的狀態手工實例化該類更方便一些。
我們先給一個通用的架構例子:
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;
接下來我們看一個具體的例子:http://blog.csdn.net/wuzhekai1985/article/details/6667020
找工作的時候,我們需要准備簡歷。假設沒有打印設備,因此需手寫簡歷,這些簡歷的內容都是一樣的。這樣有個缺陷,如果要修改簡歷中的某項,那麼所有已寫好的簡歷都要修改,工作量很大。隨著科技的進步,出現了打印設備。我們只需手寫一份,然後利用打印設備復印多份即可。如果要修改簡歷中的某項,那麼修改原始的版本就可以了,然後再復印。原始的那份手寫稿相當於是一個原型,有了它,就可以通過復印(拷貝)創造出更多的新簡歷。
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); www.2cto.com
}
}
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()函數
摘自 lbqBraveheart的專欄