C語言:備忘錄模式(shi)
							時間:2019-03-01      來源:華清遠見 
							備(bei)忘錄模(mo)式(Memento Pattern)保(bao)存一個對象的某個狀態,以便在適當的時候(hou)恢復(fu)對象。備(bei)忘錄模(mo)式屬于(yu)行為型模(mo)式。
介紹
所謂備忘錄模(mo)式(shi)就是(shi)在(zai)不破壞封裝的(de)(de)前(qian)提(ti)下,捕獲(huo)一個對象的(de)(de)內部狀(zhuang)(zhuang)態(tai),并在(zai)該對象之(zhi)外(wai)保(bao)(bao)存這個狀(zhuang)(zhuang)態(tai),這樣可以在(zai)以后將對象恢復到原先保(bao)(bao)存的(de)(de)狀(zhuang)(zhuang)態(tai)。
備忘(wang)錄模式(Memento Pattern)又叫(jiao)做快照模式(Snapshot Pattern),簡(jian)單理解為對(dui)當(dang)前對(dui)象的狀態(tai)進行備份(fen),當(dang)使用時將備份(fen)釋放(fang),覆蓋指定的對(dui)象。
何時使用
很多時(shi)候我們(men)總(zong)是(shi)需(xu)要(yao)(yao)記錄(lu)一個(ge)對象的(de)內部狀(zhuang)態(tai),這(zhe)樣做(zuo)的(de)目的(de)就是(shi)為了(le)允許用(yong)戶(hu)取消不(bu)確定(ding)或(huo)(huo)者錯(cuo)誤(wu)的(de)操(cao)(cao)作,能(neng)夠恢復到(dao)他(ta)原先的(de)狀(zhuang)態(tai),使(shi)得他(ta)有"后悔藥"可吃。以單機游(you)(you)戲進度的(de)保存為例,當通關(guan)進行到(dao)某個(ge)場景,需(xu)要(yao)(yao)攻(gong)略boss的(de)時(shi)候,通常會(hui)將(jiang)游(you)(you)戲角色的(de)狀(zhuang)態(tai)存儲(chu)起來,如(ru)果在boss大(da)戰(zhan)中失敗(bai)了(le)沒用(yong)通關(guan),則會(hui)進行讀檔(dang)操(cao)(cao)作,利用(yong)備忘錄(lu)恢復到(dao)攻(gong)略boss之前的(de)狀(zhuang)態(tai);又或(huo)(huo)是(shi)我們(men)在使(shi)用(yong)word文檔(dang)編(bian)輯時(shi),假如(ru)有一步操(cao)(cao)作錯(cuo)誤(wu)想要(yao)(yao)撤(che)銷時(shi),就會(hui)使(shi)用(yong)word提(ti)供的(de)撤(che)銷功能(neng),使(shi)編(bian)輯恢復到(dao)操(cao)(cao)作之前的(de)狀(zhuang)態(tai)。
設計
那么我們怎么來通過C語言來設計一個備忘錄模式呢?
以(yi)文(wen)本編(bian)輯為例,當(dang)我們編(bian)輯文(wen)檔通常會有一(yi)個(ge)撤銷功能,在使用(yong)撤銷功能時,會有一(yi)個(ge)相應的(de)(de)撤銷動作(zuo)。數據(ju)結構定義(yi)兩部分:撤銷的(de)(de)數據(ju)、恢復(fu)的(de)(de)操作(zuo)。
typedef struct _Action
{
int type;
struct _Action* next;
void* pData;
void (*process)(void* pData);
}Action;
對應的(de)(de)還需要(yao)有創建的(de)(de)函數和(he)恢(hui)復的(de)(de)函數,作為(wei)撤(che)銷動作的(de)(de)管理(li)者應該包括
typedef struct _Organizer
{
int number;
Action* pActionHead;
Action* (*create)();
void (*restore)(struct _Organizer* pOrganizer);
}Organizer;
數據恢復
void restore(struct _Organizer* pOrganizer)
{
Action* pHead;
assert(NULL != pOrganizer);
pHead = pOrganizer->pActionHead;
pHead->process(pHead->pData);
pOrganizer->pActionHead = pHead->next;
pOrganizer->number --;
free(pHead);
return;
}
以上就是(shi)備忘錄(lu)模式(shi)的(de)核心了(le),實(shi)現了(le)備份、撤銷、恢復動(dong)作。
備忘錄(lu)模式的優點(dian)(dian)和缺點(dian)(dian)
備忘(wang)錄(lu)模式的優點
1.有(you)時一些(xie)發起(qi)(qi)人對(dui)象(xiang)的內部信息必(bi)須保存在(zai)發起(qi)(qi)人對(dui)象(xiang)以(yi)外(wai)的地(di)方,但是必(bi)須要由發起(qi)(qi)人對(dui)象(xiang)自己讀(du)取,這時,使用備(bei)忘錄(lu)模式可以(yi)把復雜(za)的發起(qi)(qi)人內部信息對(dui)其(qi)他的對(dui)象(xiang)屏蔽起(qi)(qi)來(lai),從(cong)而(er)可以(yi)恰(qia)當(dang)地(di)保持封裝(zhuang)的邊界。
2.當發起人角色的(de)狀(zhuang)(zhuang)態(tai)(tai)改變的(de)時(shi)(shi)候,有可能這個狀(zhuang)(zhuang)態(tai)(tai)無效,這時(shi)(shi)候就可以(yi)使用暫時(shi)(shi)存儲起來的(de)備忘錄將(jiang)狀(zhuang)(zhuang)態(tai)(tai)復原(yuan)。
備忘錄(lu)模式的缺點
1.如(ru)果發起人角(jiao)色的狀態需要完整地(di)存儲到備忘錄(lu)對象(xiang)中,那么(me)在資源消耗上(shang)面(mian)備忘錄(lu)對象(xiang)會很昂貴(gui)。
2.當負責人(ren)角色(se)將一個(ge)備忘錄(lu)存儲(chu)起來的(de)(de)時候,負責人(ren)可能并(bing)不(bu)知道這個(ge)狀態會占用(yong)多(duo)大的(de)(de)存儲(chu)空間,從而無法提醒用(yong)戶一個(ge)操作是否(fou)很(hen)昂貴。
3.當發起人角色(se)的(de)狀態(tai)改(gai)變(bian)(bian)的(de)時候,有可能(neng)這個協(xie)議(yi)無效。如(ru)果狀態(tai)改(gai)變(bian)(bian)的(de)成(cheng)功率不高話(hua),不如(ru)采取(qu)“假如(ru)”協(xie)議(yi)模式(shi)。