1. 程式人生 > >(轉)設計模式(6):原型模式

(轉)設計模式(6):原型模式

定義:用原型例項指定建立物件的種類,並通過拷貝這些原型建立新的物件。

型別:建立類模式

類圖:


原型模式主要用於物件的拷貝,拷貝又分淺拷貝和深拷貝兩種。

  • 淺拷貝:就是給物件中的每個成員變數進行復制,就是把A1類中的變數直接賦給A2類中變數,屬於值傳遞,但是涉及到有new之類記憶體分配的地方,他們卻是共享記憶體的。
  • 深拷貝:就是不僅使用值傳遞,而是要每個變數都有自己一份獨立的記憶體空間,互不干擾。
預設的拷貝建構函式是淺拷貝的,如果要實現深拷貝,就需要重寫拷貝建構函式T(const T&)。

為什麼要用到深拷貝?

如果實行位拷貝,也就是把物件裡的值完全複製給另一個物件,如A=B。這時,如果B中有一個成員變數指標已經申請了記憶體,那A中的那個成員變數也指向同一塊記憶體。這就出現了問題:當B把記憶體釋放了(如:析構),這時A內的指標就是野指標了,出現執行錯誤。

程式碼實現:

#include <cstdio>


//介面
class CPrototype
{
public:
	CPrototype(){}
	virtual ~CPrototype(){}


	virtual CPrototype* Clone() = 0;
};


//實現
class CConcretePrototype : public CPrototype
{
public:
	CConcretePrototype():m_counter(0){}
	virtual ~CConcretePrototype(){}


	//拷貝建構函式
	CConcretePrototype(const CConcretePrototype& rhs)
	{
		m_counter = rhs.m_counter;
	}


	//複製自身
	virtual CPrototype* Clone()
	{
		//呼叫拷貝建構函式
		return new CConcretePrototype(*this);
	}


private:
	int m_counter;
};


int main(int argc, char **argv)
{
	//生成對像
	CPrototype* conProA = new CConcretePrototype();
	//複製自身
	CPrototype* conProB = conProA->Clone();


	delete conProA; conProA=NULL;
	delete conProB; conProB=NULL;


	return 0;
}

原型模式的優點及適用場景

優點:

  • 使用拷貝模式比直接new一個物件的開銷要小的多。
  •  使用原型模式的另一個好處是簡化物件的建立,使得建立物件就像我們在編輯文件時的複製貼上一樣簡單。
  • 可以在程式執行時(物件屬性發生了變化),得到一份內容相同的例項,但之間還不會相互干擾。
  • 基本就是你需要從A的例項得到一份與A內容相同,但是又互不干擾的例項的話,就需要使用原型模式。
缺點:必須先有一個物件例項(即原型)才能clone。

適用場景:

       因為以上優點,所以在需要重複地建立相似物件時可以考慮使用原型模式。比如需要在一個迴圈體內建立物件,假如物件建立過程比較複雜或者迴圈次數很多的話,使用原型模式不但可以簡化建立過程,而且可以使系統的整體效能提高很多。


原型模式的注意事項

       深拷貝與淺拷貝:一般的拷貝方法只會拷貝物件中的基本的資料型別,對於陣列、容器物件、引用物件等都不會拷貝,這就是淺拷貝。如果要實現深拷貝,必須將原型模式中的陣列、容器物件、引用物件等另行拷貝。