1. 程式人生 > >Prototype原型模式

Prototype原型模式

 

淺拷貝:就是給物件中的每個成員變數進行復制,就是把A1類中的變數直接賦給A2類中變數,屬於值傳遞,但是涉及到有new之類記憶體分配的地方,他們卻是共享記憶體的。

深拷貝:就是不僅使用值傳遞,而是要每個變數都有自己一份獨立的記憶體空間,互不干擾。

 

 

Prototype宣告一個複製自身的介面

ConcretePrototype實現一個複製自身的操作

Client讓一個原型複製自身從而建立一個新的物件

適用場合

1.當我們的物件型別不是開始就能確定的,而這個型別是在執行期確定的話,那麼我們通過這個型別的物件克隆出一個新的物件比較容易一些;

2.有的時候,我們需要一個物件在某個狀態下的副本,此時,我們使用原型模式是最好的選擇;例如:一個物件,經過一段處理之後,其內部的狀態發生了變化;這個時候,我們需要一個這個狀態的副本,如果直接new一個新的物件的話,但是它的狀態是不對的,此時,可以使用原型模式,將原來的物件拷貝一個出來,這個物件就和之前的物件是完全一致的了;

3.當我們處理一些比較簡單的物件時,並且物件之間的區別很小,可能就幾個屬性不同而已,那麼就可以使用原型模式來完成,省去了建立物件時的麻煩了;

4.有的時候,建立物件時,建構函式的引數很多,而自己又不完全的知道每個引數的意義,就可以使用原型模式來建立一個新的物件,不必去理會建立的過程。

優點:

1.使用拷貝模式比直接new一個物件的開銷要小的多。

2.可以在程式執行時(物件屬性發生了變化),得到一份內容相同的例項,但之間還不會相互干擾。

原型模式的優缺點:

  優點:(1):當建立物件的例項較為複雜的時候,使用原型模式可以簡化物件的建立過程,通過複製一個已有的例項可以提高例項的建立效率。

     (2):擴充套件性好,由於原型模式提供了抽象原型類,在客戶端針對抽象原型類進行程式設計,而將具體原型類寫到配置檔案中,增減或減少產品對原有系統都沒有影響。

     (3):原型模式提供了簡化的建立結構,工廠方法模式常常需要有一個與產品類等級結構相同的工廠等級結構,而原型模式不需要這樣,圓形模式中產品的複製是通過封裝在類中的克隆方法實現的,無需專門的工廠類來建立產品。

     (4):可以使用深克隆方式儲存物件的狀態,使用原型模式將物件複製一份並將其狀態儲存起來,以便在需要的時候使用(例如恢復到歷史某一狀態),可輔助實現撤銷操作。

  缺點:(1):需要為每一個類配置一個克隆方法,而且該克隆方法位於類的內部,當對已有類進行改造的時候,需要修改程式碼,違反了開閉原則。

     (2):在實現深克隆時需要編寫較為複雜的程式碼,而且當物件之間存在多重簽到引用時,為了實現深克隆,每一層物件對應的類都必須支援深克隆,實現起來會比較麻煩。

原型模式的適用環境:

  1:建立新物件成本較大(例如初始化時間長,佔用CPU多或佔太多網路資源),新物件可以通過複製已有物件來獲得,如果相似物件,則可以對其成員變數稍作修改。

  2:系統要儲存物件的狀態,而物件的狀態很小。

  3:需要避免使用分層次的工廠類來建立分層次的物件,並且類的例項物件只有一個或很少的組合狀態,通過複製原型物件得到新例項可以比使用建構函式建立一個新例項更加方便。

如果建立新物件成本較大,可以利用已有的物件進行復制來獲得。
如果系統要儲存物件的狀態,而物件的狀態變化很小,或者物件本身佔記憶體不大的時候,也可以使用原型模式配合備忘錄模式來應用。相反,如果物件的狀態變化很大,或者物件佔用的記憶體很大,那麼採用狀態模式會比原型模式更好。
需要避免使用分層次的工廠類來建立分層次的物件,並且類的例項物件只有一個或很少的幾個組合狀態,通過複製原型物件得到新例項可能比使用建構函式建立一個新例項更加方便。
 

//prototype.h
#pragma once

#ifndef PROTOTYPE_H
#define PROTOTYPE_H
#include <iostream>
using namespace std;
class Prototype
{
protected:
	Prototype() { cout << "Prototype構造"<< endl; }
public:
	virtual ~Prototype() { cout << "~Prototype析造" << endl; }
	virtual Prototype* clone() const= 0;
	virtual void printname() = 0;
};

#endif // !PROTOTYPE_H


//ConcretePrototype1.h
#pragma once

#ifndef CONCRETE_PROTOTYPE_H
#define CONCRETE_PROTOTYPE_H

#include "prototype.h"
#include <iostream>
#include <string>
using namespace std;

class ConcretePrototype1 :public Prototype
{
public:
	ConcretePrototype1(string name);
	~ConcretePrototype1();
	ConcretePrototype1(const ConcretePrototype1&other);
	virtual Prototype* clone() const;
	void printname();
private:
	string m_strName;
};


#endif // !CONCRETE_PROTOTYPE_H

 


//ConcretePrototype1.cpp
#include "ConcretePrototype1.h"

ConcretePrototype1::ConcretePrototype1(string name)
{
	m_strName = name;
	cout << "呼叫了ConcretePrototype1的建構函式" << endl;
}

ConcretePrototype1::~ConcretePrototype1()
{
	cout << "呼叫了ConcretePrototype1的解構函式" << endl;
}

ConcretePrototype1::ConcretePrototype1(const ConcretePrototype1 &other)
{
	m_strName = other.m_strName;
	cout << "呼叫了ConcretePrototype1的拷貝建構函式" << endl;
}

Prototype * ConcretePrototype1::clone() const
{
	cout << "克隆" << endl;
	return new ConcretePrototype1(*this);
}



void ConcretePrototype1::printname()
{
	cout << m_strName<< endl;
}


//main.cpp

#include "prototype.h"
#include <iostream>
#include "ConcretePrototype1.h"
using namespace std;

int main()
{
	Prototype* p = new ConcretePrototype1("rand");

	Prototype* p1 = p->clone();
	Prototype* p2 = p1->clone();
	p1->printname();
	p2->printname();
	delete p; 
	p = NULL;
	delete p1;
	p = NULL;
	delete p2;
	p = NULL;
	system("pause");
	return 0;
}

 Prototype模式和Builder模式、AbstractFactory模式都是通過一個類(物件例項)來專門負責物件的建立工作(工廠物件),它們之間的區別是:Builder模式重在複雜物件的一步步建立(並不直接返回物件),AbstractFactory模式重在產生多個相互依賴類的物件,而Prototype模式重在從自身複製自己建立新類。