设计模式 之美 -- 原型模式
文章目錄
- 1. 解決問(wèn)題
- 2. 應(yīng)用場(chǎng)景
- 3. 實(shí)現(xiàn)方式
- C++實(shí)現(xiàn)
- C語(yǔ)言實(shí)現(xiàn)
- 4. 缺點(diǎn)
- 5. 和其他三種創(chuàng)建模式的對(duì)比(單例,工廠,建造者)
1. 解決問(wèn)題
如果對(duì)象的創(chuàng)建成本較大,而同一個(gè)類的不同對(duì)象之間的差別不大(大部分字段相同),在這種情況下,我們可以利用已有對(duì)象(原型)進(jìn)行賦值(拷貝)的方式,創(chuàng)建新的對(duì)象,從而達(dá)到節(jié)省對(duì)象創(chuàng)建時(shí)間的目的。
2. 應(yīng)用場(chǎng)景
- 需要在運(yùn)行過(guò)程中,動(dòng)態(tài)的拷貝一份對(duì)象
- 需要某個(gè)對(duì)象在某個(gè)狀態(tài)下的副本
- 處理一些簡(jiǎn)單對(duì)象時(shí),對(duì)象之間的差別很小,且重建代價(jià)比較大
- 使用對(duì)象時(shí),如果對(duì)象的構(gòu)造參數(shù)很多,自己又不能完全確定參數(shù)含義,這個(gè)時(shí)候使用該模式就可以省去了解參數(shù)的過(guò)程,直接使用原型模式獲得同樣的對(duì)象即可
3. 實(shí)現(xiàn)方式
淺拷貝:只會(huì)復(fù)制對(duì)象中基本數(shù)據(jù)類型數(shù)據(jù)和引用對(duì)象的內(nèi)存地址,不會(huì)遞歸的復(fù)制引用對(duì)象,以及引用對(duì)象的引用對(duì)象。淺拷貝 存在數(shù)據(jù)被修改的風(fēng)險(xiǎn),會(huì)導(dǎo)致場(chǎng)景變得復(fù)雜多變。
深拷貝:得到一份完完全全的獨(dú)立對(duì)象,深拷貝比起淺拷貝更加耗時(shí),耗內(nèi)存。深拷貝更加安全,拷貝出來(lái)的獨(dú)立的對(duì)象不影響其他的對(duì)象。
C++實(shí)現(xiàn)
實(shí)現(xiàn)功能:一個(gè)簡(jiǎn)單的原型模式,clon成員函數(shù) 用來(lái)創(chuàng)建當(dāng)前類的實(shí)例。
#include <iostream>
#include <ctime>
#include <unistd.h>using namespace std;class Create_Prototype{
public:Create_Prototype():value(6){m_time = time((time_t*)NULL); }Create_Prototype(Create_Prototype &cp){//普通的拷貝構(gòu)造,僅僅拷貝當(dāng)前對(duì)象的基本數(shù)據(jù)類型的數(shù)據(jù)和引用對(duì)象的內(nèi)存地址。(淺拷貝)this -> value=cp.value;this -> m_time = time((time_t*)NULL);}int get_value(){ return this -> value;}Create_Prototype *clon(){return new Create_Prototype(*this);//使用的是new的方式,會(huì)分配新的對(duì)象空間(深拷貝)}time_t m_time;int value;
};int main()
{Create_Prototype *object = new Create_Prototype();cout <<"value is :" << object->value << " time is : " << object->m_time <<endl;sleep(3);/*原型模式創(chuàng)建對(duì)象 -- 深拷貝*/Create_Prototype *cp_object = object->clon();/*普通的拷貝構(gòu)造 -- 淺拷貝*///Create_Prototype *cp_object = object; //最后的輸出會(huì)出現(xiàn)異常cout <<"value is :" << cp_object->value << " time is : " << cp_object->m_time <<endl;cout << "obj address is: " << object << " value address is : " << &(object->value) << endl;cout << "cp_obj address is: " << cp_object << " value address is : " <<&(cp_object->value) << endl;delete object;delete cp_object;return 0;
}
執(zhí)行輸出如下:
淺拷貝會(huì)拋出異常(可以看到如下輸出,兩個(gè)對(duì)象指向同一塊內(nèi)存地址,最終該內(nèi)存區(qū)域會(huì)釋放兩次,導(dǎo)致異常)
value is :6 time is : 1587708400
value is :6 time is : 1587708400
obj address is: 0x1eb7010 value address is : 0x1eb7018
cp_obj address is: 0x1eb7010 value address is : 0x1eb7018
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001eb7010 ***
深拷貝(原型模式創(chuàng)建的對(duì)象)正常輸出,且每個(gè)對(duì)象有自己獨(dú)立的內(nèi)存地址
value is :6 time is : 1587708436
value is :6 time is : 1587708439
obj address is: 0x14b8010 value address is : 0x14b8018
cp_obj address is: 0x14b8030 value address is : 0x14b8038
C語(yǔ)言實(shí)現(xiàn)
實(shí)現(xiàn)功能:
動(dòng)態(tài)復(fù)制一個(gè)osd信息結(jié)構(gòu)
1、帶有copy功能的 copy函數(shù)指針
2、copy函數(shù)實(shí)現(xiàn)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>typedef struct OSD_INFO{int osd_id;int osd_type;char osd_name[16];struct OSD_INFO *(*copy)(struct OSD_INFO *);//copy函數(shù)指針
}Osd_Info;/*可以使用該原型操作,消耗很短的時(shí)間來(lái)構(gòu)造大量的同類型的對(duì)象*/
struct OSD_INFO *copy_osd_info(struct OSD_INFO *osd_info)
{struct OSD_INFO *tmp_osd_info = (struct OSD_INFO *)malloc(sizeof(struct OSD_INFO));if (tmp_osd_info == NULL){return NULL;}memmove(tmp_osd_info,osd_info,sizeof(struct OSD_INFO));return tmp_osd_info;
}int main()
{struct OSD_INFO osd_info = {0};struct OSD_INFO *other_osd = NULL;osd_info.osd_id = 1;osd_info.osd_type = 0;strcpy(osd_info.osd_name,"osd.1");osd_info.copy = copy_osd_info;other_osd = osd_info.copy(&osd_info);//原型模式 構(gòu)造一個(gè)新的結(jié)構(gòu)體變量printf("osd id is:%d\n",other_osd->osd_id);printf("osd type is:%d\n",other_osd->osd_type);printf("osd name is:%s\n",other_osd->osd_name);if(other_osd != NULL){free(other_osd);}return 0;
}
輸出如下:
osd id is:1
osd type is:0
osd name is:osd.1
4. 缺點(diǎn)
- 在有繼承相關(guān)的類圖中,每個(gè)子類都需要實(shí)現(xiàn)一個(gè)clon函數(shù),如果是新類則只需擴(kuò)展接口,但已有的類則需修改內(nèi)部源碼,違反開(kāi)閉原則
- 實(shí)現(xiàn)深拷貝的時(shí)候,如果初始化成員列表較多,則實(shí)現(xiàn)會(huì)比較復(fù)雜
5. 和其他三種創(chuàng)建模式的對(duì)比(單例,工廠,建造者)
單例模式:
在特定模式下(日志系統(tǒng)),一個(gè)類僅允許創(chuàng)建一個(gè)實(shí)例
工廠模式:
創(chuàng)建擁有相關(guān)性的不同對(duì)象(繼承同一父類或者接口的子類),由給定的參數(shù)來(lái)決定創(chuàng)建哪一種類的對(duì)象
建造者模式:
創(chuàng)建一種類型的復(fù)雜對(duì)象,通過(guò)設(shè)置不同的可選參數(shù),“定制化”地創(chuàng)建不同的對(duì)象。
原型模式:
快速創(chuàng)建對(duì)象,針對(duì)部分實(shí)例化成本較大的類,且該類需要頻繁實(shí)例化時(shí)使用原型模式更為格式。
總結(jié)
以上是生活随笔為你收集整理的设计模式 之美 -- 原型模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C++ 智能指针(unique_ptr
- 下一篇: 设计模式 之美 -- 代理模式