-
原型模式
鎖定
用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。
原型模式定義
原型模式是一種創建型設計模式,Prototype模式允許一個對象再創建另外一個可定製的對象,根本無需知道任何如何創建的細節,工作原理是:通過將一個原型對象傳給那個要發動創建的對象,這個要發動創建的對象通過請求原型對象拷貝它們自己來實施創建。
[1]
原型模式解決問題
原型模式如何使用
以勺子為例:
public abstract class AbstractSpoon implements Cloneable { String spoonName; public void setSpoonName(String spoonName) {this.spoonName = spoonName;} public String getSpoonName() {return this.spoonName;} public Object clone() { Object object = null; try { object = super.clone(); } catch (CloneNotSupportedException exception) { System.err.println("AbstractSpoon is not Cloneable"); } return object; } } 有兩個具體實現(ConcretePrototype): public class SoupSpoon extends AbstractSpoon { public SoupSpoon() { setSpoonName("Soup Spoon"); } }
調用Prototype模式很簡單:
AbstractSpoon spoon = new SoupSpoon(); AbstractSpoon spoon = new SaladSpoon();
當然也可以結合工廠模式來創建AbstractSpoon實例。
在Java中Prototype模式變成clone()方法的使用,由於Java的純潔的面向對象特性,使得在Java中使用設計模式變得很自然,兩者已經幾乎是渾然一體了。這反映在很多模式上,如Iterator遍歷模式。
帶Prototype Manager的原型模式:客户(Client)角色:客户端類向原型管理器提出創建對象的請求。
具體原型(Concrete Prototype)角色:被複制的對象。此角色需要實現抽象的原型角色所要求的接口。
代碼實現如下:
/ CplusplusPrototype.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include<iostream> #include<vector> #include<assert.h> usingnamespace std; //父類 class Resume { protected: char *name; public: Resume() {} virtual ~Resume() {} virtual Resume* Clone() { return NULL; } virtualvoid Set(char *n) {} virtualvoid Show() {} }; class ResumeA : public Resume { public: ResumeA(constchar *str); //構造函數 ResumeA(const ResumeA &r); //拷貝構造函數 ~ResumeA(); //析構函數 ResumeA* Clone(); //克隆,關鍵所在 void Show(); //顯示內容 }; ResumeA::ResumeA(constchar *str) { if(str == NULL) { name = newchar[1]; name[0] = '\0'; } else { name = newchar[strlen(str)+1]; strcpy(name, str); } } ResumeA::~ResumeA() { delete [] name;} ResumeA::ResumeA(const ResumeA &r) { name = newchar[strlen(r.name)+1]; strcpy(name, r.name); } ResumeA* ResumeA::Clone() { returnnew ResumeA(*this); } void ResumeA::Show() { cout<<"ResumeA name : "<<name<<endl; } class ResumeB : public Resume { public: ResumeB(constchar *str); //構造函數 ResumeB(const ResumeB &r); //拷貝構造函數 ~ResumeB(); //析構函數 ResumeB* Clone(); //克隆,關鍵所在 void Show(); //顯示內容 }; ResumeB::ResumeB(constchar *str) { if(str == NULL) { name = newchar[1]; name[0] = '\0'; } else { name = newchar[strlen(str)+1]; strcpy(name, str); } } ResumeB::~ResumeB() { delete [] name;} ResumeB::ResumeB(const ResumeB &r) { name = newchar[strlen(r.name)+1]; strcpy(name, r.name); } ResumeB* ResumeB::Clone() { returnnew ResumeB(*this); } void ResumeB::Show() { cout<<"ResumeB name : "<<name<<endl; } class ResumeManager { private: vector<Resume *> mResume; public: ResumeManager() { } void add(Resume * resume) { mResume.push_back(resume); } Resume * get(int index) const { assert(index>=0 && index<mResume.size()); return mResume[index]; } }; int _tmain(int argc, _TCHAR* argv[]) { ResumeManager *manager = new ResumeManager(); Resume *r1 = new ResumeA("A"); Resume *r2 = new ResumeB("B"); manager->add(r1); manager->add(r2); manager->get(0)->Show(); manager->get(1)->Show(); Resume *r3 = manager->get(0)->Clone(); Resume *r4 = manager->get(1)->Clone(); //刪除r1,r2 delete r1; delete r2; r1 = r2 = NULL; //深拷貝所以對r3,r4無影響 r3->Show(); r4->Show(); delete r3; delete r4; r3 = r4 = NULL; return 0; }