设计模式 之美 -- 原型模式
文章目錄
- 1. 解決問題
- 2. 應用場景
- 3. 實現方式
- C++實現
- C語言實現
- 4. 缺點
- 5. 和其他三種創建模式的對比(單例,工廠,建造者)
1. 解決問題
如果對象的創建成本較大,而同一個類的不同對象之間的差別不大(大部分字段相同),在這種情況下,我們可以利用已有對象(原型)進行賦值(拷貝)的方式,創建新的對象,從而達到節省對象創建時間的目的。
2. 應用場景
- 需要在運行過程中,動態的拷貝一份對象
- 需要某個對象在某個狀態下的副本
- 處理一些簡單對象時,對象之間的差別很小,且重建代價比較大
- 使用對象時,如果對象的構造參數很多,自己又不能完全確定參數含義,這個時候使用該模式就可以省去了解參數的過程,直接使用原型模式獲得同樣的對象即可
3. 實現方式
淺拷貝:只會復制對象中基本數據類型數據和引用對象的內存地址,不會遞歸的復制引用對象,以及引用對象的引用對象。淺拷貝 存在數據被修改的風險,會導致場景變得復雜多變。
深拷貝:得到一份完完全全的獨立對象,深拷貝比起淺拷貝更加耗時,耗內存。深拷貝更加安全,拷貝出來的獨立的對象不影響其他的對象。
C++實現
實現功能:一個簡單的原型模式,clon成員函數 用來創建當前類的實例。
#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){//普通的拷貝構造,僅僅拷貝當前對象的基本數據類型的數據和引用對象的內存地址。(淺拷貝)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的方式,會分配新的對象空間(深拷貝)}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);/*原型模式創建對象 -- 深拷貝*/Create_Prototype *cp_object = object->clon();/*普通的拷貝構造 -- 淺拷貝*///Create_Prototype *cp_object = object; //最后的輸出會出現異常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;
}
執行輸出如下:
淺拷貝會拋出異常(可以看到如下輸出,兩個對象指向同一塊內存地址,最終該內存區域會釋放兩次,導致異常)
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 ***
深拷貝(原型模式創建的對象)正常輸出,且每個對象有自己獨立的內存地址
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語言實現
實現功能:
動態復制一個osd信息結構
1、帶有copy功能的 copy函數指針
2、copy函數實現
#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函數指針
}Osd_Info;/*可以使用該原型操作,消耗很短的時間來構造大量的同類型的對象*/
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);//原型模式 構造一個新的結構體變量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. 缺點
- 在有繼承相關的類圖中,每個子類都需要實現一個clon函數,如果是新類則只需擴展接口,但已有的類則需修改內部源碼,違反開閉原則
- 實現深拷貝的時候,如果初始化成員列表較多,則實現會比較復雜
5. 和其他三種創建模式的對比(單例,工廠,建造者)
單例模式:
在特定模式下(日志系統),一個類僅允許創建一個實例
工廠模式:
創建擁有相關性的不同對象(繼承同一父類或者接口的子類),由給定的參數來決定創建哪一種類的對象
建造者模式:
創建一種類型的復雜對象,通過設置不同的可選參數,“定制化”地創建不同的對象。
原型模式:
快速創建對象,針對部分實例化成本較大的類,且該類需要頻繁實例化時使用原型模式更為格式。
總結
以上是生活随笔為你收集整理的设计模式 之美 -- 原型模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ 智能指针(unique_ptr
- 下一篇: 谁来教我认识各种衣服的颜色,发现出了黑白