DP書上的定義爲:用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。其中有一個詞很重要,那就是拷貝。可以說,拷貝是原型模式的精髓所在。舉個現實中的例子來介紹原型模式。找工作的時候,我們需要準備簡歷。假設沒有打印設備,因此需手寫簡歷,這些簡歷的內容都是一樣的。這樣有個缺陷,如果要修改簡歷中的某項,那麼所有已寫好的簡歷都要修改,工作量很大。隨着科技的進步,出現了打印設備。我們只需手寫一份,然後利用打印設備複印多份即可。如果要修改簡歷中的某項,那麼修改原始的版本就可以了,然後再複印。原始的那份手寫稿相當於是一個原型,有了它,就可以通過複印(拷貝)創造出更多的新簡歷。這就是原型模式的基本思想。下面給出原型模式的UML圖,以剛纔那個例子爲實例。
原型模式實現的關鍵就是實現Clone函數,對於C++來說,其實就是拷貝構造函數,需實現深拷貝,下面給出一種實現。
- //父類
- class Resume
- {
- protected:
- char *name;
- public:
- Resume() {}
- virtual ~Resume() {}
- virtual Resume* Clone() { return NULL; }
- virtual void Set(char *n) {}
- virtual void Show() {}
- };
- //父類
- class Resume
- {
- protected:
- char *name;
- public:
- Resume() {}
- virtual ~Resume() {}
- virtual Resume* Clone() { return NULL; }
- virtual void Set(char *n) {}
- virtual void Show() {}
- };
- class ResumeA : public Resume
- {
- public:
- ResumeA(const char *str); //構造函數
- ResumeA(const ResumeA &r); //拷貝構造函數
- ~ResumeA(); //析構函數
- ResumeA* Clone(); //克隆,關鍵所在
- void Show(); //顯示內容
- };
- 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;
- }
- class ResumeA : public Resume
- {
- public:
- ResumeA(const char *str); //構造函數
- ResumeA(const ResumeA &r); //拷貝構造函數
- ~ResumeA(); //析構函數
- ResumeA* Clone(); //克隆,關鍵所在
- void Show(); //顯示內容
- };
- 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;
- }
這裏只給出了ResumeA的實現,ResumeB的實現類似。使用的方式如下:
- 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;
- }
- 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;
- }
最近有個招聘會,可以帶上簡歷去應聘了。但是,其中有一家公司不接受簡歷,而是給應聘者發了一張簡歷表,上面有基本信息、教育背景、工作經歷等欄,讓應聘者按照要求填寫完整。每個人拿到這份表格後,就開始填寫。如果用程序實現這個過程,該如何做呢?一種方案就是用模板方法模式:定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。我們的例子中,操作就是填寫簡歷這一過程,我們可以在父類中定義操作的算法骨架,而具體的實現由子類完成。下面給出它的UML圖。
其中FillResume() 定義了操作的骨架,依次調用子類實現的函數。相當於每個人填寫簡歷的實際過程。接着給出相應的C++代碼。
- //簡歷
- class Resume
- {
- protected: //保護成員
- virtual void SetPersonalInfo() {}
- virtual void SetEducation() {}
- virtual void SetWorkExp() {}
- public:
- void FillResume()
- {
- SetPersonalInfo();
- SetEducation();
- SetWorkExp();
- }
- };
- class ResumeA: public Resume
- {
- protected:
- void SetPersonalInfo() { cout<<"A's PersonalInfo"<<endl; }
- void SetEducation() { cout<<"A's Education"<<endl; }
- void SetWorkExp() { cout<<"A's Work Experience"<<endl; }
- };
- class ResumeB: public Resume
- {
- protected:
- void SetPersonalInfo() { cout<<"B's PersonalInfo"<<endl; }
- void SetEducation() { cout<<"B's Education"<<endl; }
- void SetWorkExp() { cout<<"B's Work Experience"<<endl; }
- };
- //簡歷
- class Resume
- {
- protected: //保護成員
- virtual void SetPersonalInfo() {}
- virtual void SetEducation() {}
- virtual void SetWorkExp() {}
- public:
- void FillResume()
- {
- SetPersonalInfo();
- SetEducation();
- SetWorkExp();
- }
- };
- class ResumeA: public Resume
- {
- protected:
- void SetPersonalInfo() { cout<<"A's PersonalInfo"<<endl; }
- void SetEducation() { cout<<"A's Education"<<endl; }
- void SetWorkExp() { cout<<"A's Work Experience"<<endl; }
- };
- class ResumeB: public Resume
- {
- protected:
- void SetPersonalInfo() { cout<<"B's PersonalInfo"<<endl; }
- void SetEducation() { cout<<"B's Education"<<endl; }
- void SetWorkExp() { cout<<"B's Work Experience"<<endl; }
- };
使用方式如下:
- int main()
- {
- Resume *r1;
- r1 = new ResumeA();
- r1->FillResume();
- delete r1;
- r1 = new ResumeB();
- r1->FillResume();
- delete r1;
- r1 = NULL;
- return 0;
- }
- int main()
- {
- Resume *r1;
- r1 = new ResumeA();
- r1->FillResume();
- delete r1;
- r1 = new ResumeB();
- r1->FillResume();
- delete r1;
- r1 = NULL;
- return 0;
- }