什么是原型模式? 在GOF的《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》中是這樣說的:用原型實(shí)例指定創(chuàng)建對(duì)象的種類,,并且通過拷貝這些原型創(chuàng)建新的對(duì)象,。這這個(gè)定義中,,最重要的一個(gè)詞是“拷貝”,也就是口頭上的復(fù)制,,而這個(gè)拷貝,,也就是原型模式的精髓所在。 舉一個(gè)最簡(jiǎn)單的例子來說明原型模式:記得上小學(xué)的時(shí)候,,老師把需要做的課外習(xí)題寫到黑板上,,而下面的我們都要把這些題抄寫到自己的本子上,回家做好,,第二天交上來,,也就是每道題,,全班50個(gè)人,每個(gè)人都要抄寫一遍,。按照現(xiàn)在的時(shí)間理論來說,,就是浪費(fèi)了50個(gè)人的時(shí)間,。但是,,那個(gè)時(shí)候條件限制,老師也是不得已而為之。現(xiàn)在好了,,老師做一份電子版的習(xí)題,,打印一份,,然后拿著這份打印的原版,就可以復(fù)制出50份,。 結(jié)合原型模式的概念進(jìn)行分析,老師打印出來的那一份,,就是“原型”,而復(fù)制出來的那50份,,就是使用的“拷貝”,。而原型模式就是這么簡(jiǎn)單的一個(gè)道理,通過現(xiàn)有的東西,,再復(fù)制出一個(gè)來,。 為什么要使用原型模式,? 原型模式和建造者模式、工廠方法模式一樣,,都屬于創(chuàng)建型模式的一種,。簡(jiǎn)單的來說,我們使用原型模式,,就是為了創(chuàng)建對(duì)象,。但是,在以下場(chǎng)景下,,使用原型模式是最好的選擇: 1.當(dāng)我們的對(duì)象類型不是開始就能確定的,,而這個(gè)類型是在運(yùn)行期確定的話,,那么我們通過這個(gè)類型的對(duì)象克隆出一個(gè)新的對(duì)象比較容易一些; 2.有的時(shí)候,,我們需要一個(gè)對(duì)象在某個(gè)狀態(tài)下的副本,,此時(shí),我們使用原型模式是最好的選擇,;例如:一個(gè)對(duì)象,,經(jīng)過一段處理之后,,其內(nèi)部的狀態(tài)發(fā)生了變化;這個(gè)時(shí)候,,我們需要一個(gè)這個(gè)狀態(tài)的副本,如果直接new一個(gè)新的對(duì)象的話,但是它的狀態(tài)是不對(duì)的,,此時(shí),,可以使用原型模式,將原來的對(duì)象拷貝一個(gè)出來,,這個(gè)對(duì)象就和之前的對(duì)象是完全一致的了; 3.當(dāng)我們處理一些比較簡(jiǎn)單的對(duì)象時(shí),,并且對(duì)象之間的區(qū)別很小,,可能就幾個(gè)屬性不同而已,那么就可以使用原型模式來完成,,省去了創(chuàng)建對(duì)象時(shí)的麻煩了,; 4.有的時(shí)候,創(chuàng)建對(duì)象時(shí),,構(gòu)造函數(shù)的參數(shù)很多,,而自己又不完全的知道每個(gè)參數(shù)的意義,就可以使用原型模式來創(chuàng)建一個(gè)新的對(duì)象,,不必去理會(huì)創(chuàng)建的過程,,讓創(chuàng)建過程見鬼去吧。 用UML類圖表示原型模式
由于克隆需要一個(gè)原型,,而上面的類圖中Prototype就這個(gè)原型,Prototype定義了克隆自身的Clone接口,,由派生類進(jìn)行實(shí)現(xiàn),,而實(shí)現(xiàn)原型模式的重點(diǎn)就在于這個(gè)Clone接口的實(shí)現(xiàn)。ConcretePrototype1類和ConcretePrototype2類繼承自Prototype類,,并實(shí)現(xiàn)Clone接口,,實(shí)現(xiàn)克隆自身的操作;同時(shí),,在ConcretePrototype1類和ConcretePrototype2類中需要重寫默認(rèn)的復(fù)制構(gòu)造函數(shù),,供Clone函數(shù)調(diào)用,Clone就是通過在內(nèi)部調(diào)用重寫的復(fù)制構(gòu)造函數(shù)實(shí)現(xiàn)的,。在后續(xù)的編碼過程中,,如果某個(gè)類需要實(shí)現(xiàn)Clone功能,就只需要繼承Prototype類,,然后重寫自己的默認(rèn)復(fù)制構(gòu)造函數(shù)就好了,。好比在C#中就提供了ICloneable接口,,當(dāng)某個(gè)類需要實(shí)現(xiàn)原型模式時(shí),只需要實(shí)現(xiàn)這個(gè)接口的道理是一樣的,。 代碼實(shí)現(xiàn) 復(fù)制代碼 代碼如下: /* ** FileName : PrototypePatternDemo ** Author : Jelly Young ** Date : 2013/11/25 ** Description : More information, please go to http://www.jb51.net */ #include <iostream> using namespace std; //接口 class Prototype { public : Prototype(){} virtual ~Prototype(){} virtual Prototype * Clone() = 0; }; //實(shí)現(xiàn) class ConcretePrototype : public Prototype { public : ConcretePrototype():m_counter(0){} virtual ~ConcretePrototype(){} //拷貝構(gòu)造函數(shù) ConcretePrototype( const ConcretePrototype & rhs) { m_counter = rhs .m_counter; } //復(fù)制自身 virtual ConcretePrototype * Clone() { //調(diào)用拷貝構(gòu)造函數(shù) return new ConcretePrototype (*this ); } private : int m_counter; }; int main(int argc , char **argv) { //生成對(duì)像 ConcretePrototype * conProA = new ConcretePrototype (); //復(fù)制自身 ConcretePrototype * conProB = conProA->Clone(); delete conProA; conProA= NULL ; delete conProB; conProB= NULL ; return 0; }
上述代碼實(shí)現(xiàn)了一個(gè)最簡(jiǎn)單的原型模式,,但是已經(jīng)將原型模式的基本實(shí)現(xiàn)原理展現(xiàn)出來了。而有的時(shí)候,,當(dāng)調(diào)用Clone獲得了一個(gè)復(fù)制的對(duì)象以后,,需要改變對(duì)象的狀態(tài),此時(shí)就可能需要在ConcretePrototype類中添加一個(gè)Initialize操作,,專門用于初始化克隆對(duì)象,。由于在Clone的內(nèi)部調(diào)用的是復(fù)制構(gòu)造函數(shù),而此處又涉及到深復(fù)制和淺復(fù)制的問題,。所以,,在實(shí)際操作的過程中,這些問題,,都需要進(jìn)行仔細(xì)的考慮。 與其它創(chuàng)建型模式的比較 工廠方法模式,、抽象工廠模式,、建造者模式和原型模式都是創(chuàng)建型模式。工廠方法模式適用于生產(chǎn)較復(fù)雜,,一個(gè)工廠生產(chǎn)單一的一種產(chǎn)品的時(shí)候,;抽象工廠模式適用于一個(gè)工廠生產(chǎn)多個(gè)相互依賴的產(chǎn)品;建造者模式著重于復(fù)雜對(duì)象的一步一步創(chuàng)建,,組裝產(chǎn)品的過程,,并在創(chuàng)建的過程中,可以控制每一個(gè)簡(jiǎn)單對(duì)象的創(chuàng)建,;原型模式則更強(qiáng)調(diào)的是從自身復(fù)制自己,,創(chuàng)建要給和自己一模一樣的對(duì)象。 總結(jié) 原型模式作為創(chuàng)建型模式中最特殊的一個(gè)模式,,具體的創(chuàng)建過程,,是由對(duì)象本身提供,這樣我們?cè)诤芏嗟膱?chǎng)景下可以很方便的快速的構(gòu)建新的對(duì)象,。但是,,原型模式的最大缺點(diǎn)是繼承原型的子類都要實(shí)現(xiàn)Clone操作,這個(gè)是很困難的,。例如,,當(dāng)所考慮的類已經(jīng)存在時(shí)就難以新增Clone操作。當(dāng)內(nèi)部包括一些不支持拷貝或者有循環(huán)引用的對(duì)象時(shí),,實(shí)現(xiàn)克隆可能也會(huì)很困難,。說以說,,每一種設(shè)計(jì)模式都有它的優(yōu)點(diǎn)和缺點(diǎn),在設(shè)計(jì)的時(shí)候,,我們需要進(jìn)行權(quán)衡各方面的因素,,揚(yáng)長(zhǎng)避短。 |
|