在GOF的《設計模式:可復用面向對象軟件的基礎》中是這樣說的:用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。這這個定義中,最重要的一個詞是“拷貝”,也就是口頭上的復制,而這個拷貝,也就是原型模式的精髓所在。
舉一個最簡單的例子來說明原型模式:記得上小學的時候,老師把需要做的課外習題寫到黑板上,而下面的我們都要把這些題抄寫到自己的本子上,回家做好,第二天交上來,也就是每道題,全班50個人,每個人都要抄寫一遍。按照現在的時間理論來說,就是浪費了50個人的時間。但是,那個時候條件限制,老師也是不得已而為之。現在好了,老師做一份電子版的習題,打印一份,然後拿著這份打印的原版,就可以復制出50份。
結合原型模式的概念進行分析,老師打印出來的那一份,就是“原型”,而復制出來的那50份,就是使用的“拷貝”。而原型模式就是這麼簡單的一個道理,通過現有的東西,再復制出一個來。
原型模式和建造者模式、工廠方法模式一樣,都屬於創建型模式的一種。簡單的來說,我們使用原型模式,就是為了創建對象。但是,在以下場景下,使用原型模式是最好的選擇:
所以,在上述的的情況下,在設計的時候,適當的考慮一下原型模式,減少對應的工作量,減少程序的復雜度,提高效率。
由於克隆需要一個原型,而上面的類圖中Prototype就這個原型,Prototype定義了克隆自身的Clone接口,由派生類進行實現,而實現原型模式的重點就在於這個Clone接口的實現。ConcretePrototype1類和ConcretePrototype2類繼承自Prototype類,並實現Clone接口,實現克隆自身的操作;同時,在ConcretePrototype1類和ConcretePrototype2類中需要重寫默認的復制構造函數,供Clone函數調用,Clone就是通過在內部調用重寫的復制構造函數實現的。在後續的編碼過程中,如果某個類需要實現Clone功能,就只需要繼承Prototype類,然後重寫自己的默認復制構造函數就好了。好比在C#中就提供了ICloneable接口,當某個類需要實現原型模式時,只需要實現這個接口的道理是一樣的。
/*
** FileName : PrototypePatternDemo
** Author : Jelly Young
** Date : 2013/11/25
** Description : More information, please go to http://www.jellythink.com
*/#include <iostream>using namespace std;//接口class Prototype{public :
Prototype(){}
virtual ~Prototype(){}
virtual Prototype * Clone() = 0;};//實現class ConcretePrototype : public Prototype{public :
ConcretePrototype():m_counter(0){}
virtual ~ConcretePrototype(){}
//拷貝構造函數
ConcretePrototype( const ConcretePrototype & rhs)
{
m_counter = rhs .m_counter;
}
//復制自身
virtual ConcretePrototype * Clone()
{
//調用拷貝構造函數
return new ConcretePrototype (*this );
}private :
int m_counter;};int main(int argc , char **argv){
//生成對像
ConcretePrototype * conProA = new ConcretePrototype ();
//復制自身
ConcretePrototype * conProB = conProA->Clone();
delete conProA;
conProA= NULL ;
delete conProB;
conProB= NULL ;
return 0;}
上述代碼實現了一個最簡單的原型模式,但是已經將原型模式的基本實現原理展現出來了。而有的時候,當調用Clone獲得了一個復制的對象以後,需要改變對象的狀態,此時就可能需要在ConcretePrototype類中添加一個Initialize操作,專門用於初始化克隆對象。由於在Clone的內部調用的是復制構造函數,而此處又涉及到深復制和淺復制的問題。所以,在實際操作的過程中,這些問題,都需要進行仔細的考慮。
工廠方法模式、抽象工廠模式、建造者模式和原型模式都是創建型模式。工廠方法模式適用於生產較復雜,一個工廠生產單一的一種產品的時候;抽象工廠模式適用於一個工廠生產多個相互依賴的產品;建造者模式著重於復雜對象的一步一步創建,組裝產品的過程,並在創建的過程中,可以控制每一個簡單對象的創建;原型模式則更強調的是從自身復制自己,創建要給和自己一模一樣的對象。
原型模式作為創建型模式中最特殊的一個模式,具體的創建過程,是由對象本身提供,這樣我們在很多的場景下可以很方便的快速的構建新的對象。但是,原型模式的最大缺點是繼承原型的子類都要實現Clone操作,這個是很困難的。例如,當所考慮的類已經存在時就難以新增Clone操作。當內部包括一些不支持拷貝或者有循環引用的對象時,實現克隆可能也會很困難。說以說,每一種設計模式都有它的優點和缺點,在設計的時候,我們需要進行權衡各方面的因素,揚長避短。