面試必備之原型模式

一、定義

     Prototype模式是一種對象創建型模式,它用一個已經創建的實例作爲原型,通過複製該原型對象來創建一個和原型相同或相似的新對象。在這裏,原型實例指定了要創建的對象的種類。用這種方式創建對象非常高效,根本無須知道對象創建的細節。

  1. 由原型對象自身創建目標對象。即對象創建這一動作發自原型對象本身。
  2. 目標對象是原型對象的一個克隆。即通過Prototype模式創建的對象,不僅僅與原型對象具有相同的結構,還與原型對象具有相同的值。
  3. 根據對象克隆深度層次的不同,有淺度克隆與深度克隆。
    關於深淺克隆,需要理解c++拷貝複製函數,請參考:c++拷貝構造函數詳解

二、角色

1.抽象原型類:
     規定了具體原型對象必須實現的接口。
2.具體原型類:
     實現抽象原型類的 clone() 方法,它是可被複制的對象。
3.訪問類:
     使用具體原型類中的 clone() 方法來複制新的對象。

UML類圖如下:
在這裏插入圖片描述

三、實現

#include<iostream>
using namespace std;

//抽象原型
class Person{
public:
	virtual Person* clone() = 0;
	virtual void printMSG() = 0;
};

//具體原型
class JavaPragramer:public Person{
private:
	string m_name;
	int m_age;
	char *m_motto;
public:
	JavaPragramer(){
	
	}
	JavaPragramer(const string name,const int age,const char* motto){
		this->m_name = name;
		this->m_age = age;
		if(motto == nullptr){
			this->m_motto = new char[1];
			this->m_motto[0] = '\0';
		}else{
		    int len = strlen(motto) + 1;
			this->m_motto = new char[len];
			strcpy(this->m_motto,motto);
		}
	}
	~JavaPragramer(){
		if(this->m_motto != nullptr){
			delete this->m_motto;
			this->m_motto = nullptr;
		}
	}
	//拷貝構造函數
	JavaPragramer(const JavaPragramer &p){
		this->m_name = p.m_name;
		this->m_age = p.m_age;

		//存在指針成員變量,進行深拷貝
		if(p.m_motto == nullptr){
			this->m_motto = new char[1];
			this->m_motto[0] = '\0';
		}else{
		    int len = strlen(p.m_motto) + 1;
			this->m_motto = new char[len];
			strcpy(this->m_motto,p.m_motto);
		}
	}
	//克隆
	Person* clone(){
		Person * p = new JavaPragramer(*this);//通過拷貝構造函數實現克隆
		return p;
	}
	void printMSG(){
		cout<<this->m_name.c_str() <<" : "<<this->m_age<<" : "<<this->m_motto<<endl;
	}
};

class CplusplusPragramer:public Person{
private:
	string m_name;
	int m_age;
	char *m_motto;
public:
	CplusplusPragramer(){
	
	}
	CplusplusPragramer(const string name,const int age,const char* motto){
		this->m_name = name;
		this->m_age = age;
		if(motto == nullptr){
			this->m_motto = new char[1];
			this->m_motto[0] = '\0';
		}else{
		    int len = strlen(motto) + 1;
			this->m_motto = new char[len];
			strcpy(this->m_motto,motto);
		}
	}
	~CplusplusPragramer(){
		if(this->m_motto != nullptr){
			delete this->m_motto;
			this->m_motto = nullptr;
		}
	}
	//拷貝構造函數
	CplusplusPragramer(const CplusplusPragramer &p){
		this->m_name = p.m_name;
		this->m_age = p.m_age;

		//存在指針成員變量,進行深拷貝
		if(p.m_motto == nullptr){
			this->m_motto = new char[1];
			this->m_motto[0] = '\0';
		}else{
		    int len = strlen(p.m_motto) + 1;
			this->m_motto = new char[len];
			strcpy(this->m_motto,p.m_motto);
		}
	}
	//克隆
	Person* clone(){
		Person * p = new CplusplusPragramer(*this);
		return p;
	}
	void printMSG(){
		cout<<this->m_name.c_str() <<" : "<<this->m_age<<" : "<<this->m_motto<<endl;
	}
};

int main(){
	//創建一個java實例原型
	Person *javaPragramer = new JavaPragramer("Tom",22,"Java是最好的語言");
	javaPragramer->printMSG();
	
	//克隆person
	Person *javaPragramer2 = javaPragramer->clone();
	javaPragramer2->printMSG();
	delete javaPragramer;
	delete javaPragramer2;

	//創建一個c++實例原型
	Person *cplusplusPragramer = new CplusplusPragramer("Jack",25,"c++是改變世界的語言");
	cplusplusPragramer->printMSG();
	
	//克隆person
	Person *cplusplusPragramer2 = cplusplusPragramer->clone();
	cplusplusPragramer2->printMSG();
	delete cplusplusPragramer;
	delete cplusplusPragramer2;
	return 0 ;
}

四、應用場景

1.類初始化需要消化非常多的資源,這個資源包括數據、硬件資源等,通過原型拷貝避免這些消耗。
2.通過new一個對象需要非常繁瑣的數據準備或訪問權限,可以使用原型模式。
3.一個對象需要提供給其他對象訪問,而且各個調用者可能需要修改其值,可以考慮使用原型模式拷貝多個對象供調用者使用,即保護性拷貝。

五、與其他創建型模式區別

相同的點:
Prototype模式、Builder模式、AbstractFactory模式都是通過一個類(對象實例)來專門負責對象的創建工作。

不同點:
Builder模式重在複雜對象的一步步創建。
AbstractFactory模式重在產生多個相互依賴類的對象。
Prototype模式重在從自身複製自己創建新類。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章