C++使用備忘錄模式實(shí)現(xiàn)對(duì)象狀態(tài)保存與恢復(fù)功能
引言
在軟件開(kāi)發(fā)中,我們經(jīng)常需要實(shí)現(xiàn)撤銷操作、歷史記錄或狀態(tài)回滾等功能。備忘錄模式(Memento Pattern)正是為解決這類問(wèn)題而生的設(shè)計(jì)模式。本文將深入探討備忘錄模式在C++中的實(shí)現(xiàn)與應(yīng)用,幫助開(kāi)發(fā)者掌握這一強(qiáng)大的設(shè)計(jì)工具。
備忘錄模式概述
備忘錄模式是一種行為設(shè)計(jì)模式,它允許在不破壞封裝性的前提下捕獲并外部化一個(gè)對(duì)象的內(nèi)部狀態(tài),以便以后可以將該對(duì)象恢復(fù)到原先保存的狀態(tài)【1†source】。該模式特別適合需要實(shí)現(xiàn)撤銷操作、歷史記錄或快照功能的場(chǎng)景【1†source】【2†source】。
核心角色解析
1. Originator(發(fā)起人)
Originator是需要保存狀態(tài)的對(duì)象,它:
- 負(fù)責(zé)創(chuàng)建備忘錄并記錄當(dāng)前狀態(tài)
- 可以使用備忘錄恢復(fù)之前的狀態(tài)
- 知道如何正確保存和恢復(fù)自身狀態(tài)【1†source】【2†source】
2. Memento(備忘錄)
Memento是存儲(chǔ)Originator狀態(tài)的對(duì)象,特點(diǎn)包括:
- 存儲(chǔ)Originator的內(nèi)部狀態(tài)
- 提供兩個(gè)接口:寬接口(Originator使用)和窄接口(其他對(duì)象使用)【1†source】
- 確保狀態(tài)的封裝性不被破壞
3. Caretaker(管理者)
Caretaker負(fù)責(zé)管理備忘錄,其職責(zé)是:
- 保存?zhèn)渫泴?duì)象
- 不操作備忘錄內(nèi)容
- 只能通過(guò)窄接口與備忘錄交互【1†source】
設(shè)計(jì)原則體現(xiàn)
備忘錄模式很好地體現(xiàn)了多個(gè)面向?qū)ο笤O(shè)計(jì)原則:
- 單一職責(zé)原則:將狀態(tài)保存的職責(zé)從Originator中分離出來(lái)【3†source】【7†source】,使Originator可以專注于核心業(yè)務(wù)邏輯【3†source】。
- 開(kāi)閉原則:不需要修改Originator類就能擴(kuò)展?fàn)顟B(tài)保存功能【3†source】,通過(guò)新增備忘錄類實(shí)現(xiàn)這一擴(kuò)展【3†source】。
- 迪米特法則:Caretaker不直接操作Memento內(nèi)部細(xì)節(jié)【3†source】【6†source】,有效降低了系統(tǒng)耦合度【6†source】。
C++實(shí)現(xiàn)示例
#include <iostream>
#include <string>
#include <vector>
// 備忘錄類
class Memento {
private:
std::string state;
// 只有Originator可以訪問(wèn)私有成員
friend class Originator;
Memento(const std::string& s) : state(s) {}
std::string GetState() const { return state; }
};
// 發(fā)起人類
class Originator {
private:
std::string state;
public:
void SetState(const std::string& s) {
std::cout << "設(shè)置狀態(tài): " << s << std::endl;
state = s;
}
Memento* CreateMemento() {
return new Memento(state);
}
void RestoreFromMemento(const Memento* m) {
state = m->GetState();
std::cout << "恢復(fù)狀態(tài): " << state << std::endl;
}
};
// 管理者類
class Caretaker {
private:
std::vector<Memento*> mementos;
Originator* originator;
public:
Caretaker(Originator* orig) : originator(orig) {}
~Caretaker() {
for(auto m : mementos) delete m;
}
void Save() {
mementos.push_back(originator->CreateMemento());
}
void Undo() {
if(mementos.empty()) return;
Memento* m = mementos.back();
originator->RestoreFromMemento(m);
mementos.pop_back();
delete m;
}
};
// 使用示例
int main() {
Originator originator;
Caretaker caretaker(&originator);
originator.SetState("狀態(tài)1");
caretaker.Save();
originator.SetState("狀態(tài)2");
caretaker.Save();
originator.SetState("狀態(tài)3");
// 執(zhí)行撤銷
caretaker.Undo(); // 恢復(fù)到狀態(tài)2
caretaker.Undo(); // 恢復(fù)到狀態(tài)1
return 0;
}
典型應(yīng)用場(chǎng)景
備忘錄模式在以下場(chǎng)景中特別有用:
- 撤銷/重做功能:如文本編輯器中的撤銷操作【1†source】【2†source】
- 事務(wù)回滾系統(tǒng):數(shù)據(jù)庫(kù)操作的事務(wù)管理【1†source】【5†source】
- 游戲存檔系統(tǒng):保存和恢復(fù)游戲進(jìn)度【1†source】【2†source】
- 配置管理:保存和恢復(fù)系統(tǒng)配置狀態(tài)
高級(jí)特性與優(yōu)化
1. 增量備忘錄
對(duì)于狀態(tài)變化不大的場(chǎng)景,可以只保存變化部分【1†source】,這能顯著減少內(nèi)存消耗【1†source】。
2. 序列化支持
通過(guò)序列化技術(shù),可以將備忘錄狀態(tài)持久化存儲(chǔ)【2†source】,如保存到文件或數(shù)據(jù)庫(kù)中【1†source】。
3. 線程安全考慮
在多線程環(huán)境中使用時(shí)【2†source】,需要添加適當(dāng)?shù)耐綑C(jī)制來(lái)保證狀態(tài)的一致性【1†source】。
與其他模式的協(xié)作
備忘錄模式常與其他設(shè)計(jì)模式配合使用:
- 命令模式:實(shí)現(xiàn)可撤銷的操作【1†source】【2†source】
- 原型模式:通過(guò)克隆對(duì)象狀態(tài)來(lái)優(yōu)化備忘錄創(chuàng)建【1†source】【2†source】
- 狀態(tài)模式:保存不同狀態(tài)配置【1†source】【2†source】
注意事項(xiàng)
- 內(nèi)存消耗:對(duì)于大對(duì)象狀態(tài),需考慮內(nèi)存使用情況【8†source】,可能影響系統(tǒng)性能【1†source】
- C++內(nèi)存管理:特別注意指針和內(nèi)存泄漏問(wèn)題【1†source】【2†source】
- 替代方案:原型模式有時(shí)可作為更簡(jiǎn)單的替代方案【2†source】
總結(jié)
備忘錄模式是面向?qū)ο笤O(shè)計(jì)原則的優(yōu)秀實(shí)踐【9†source】,通過(guò)狀態(tài)封裝實(shí)現(xiàn)了靈活的回滾機(jī)制【1†source】【2†source】。合理使用該模式可以顯著提高系統(tǒng)的可維護(hù)性和擴(kuò)展性【3†source】【7†source】。在C++中實(shí)現(xiàn)時(shí),需要特別注意內(nèi)存管理和線程安全等問(wèn)題。掌握備忘錄模式將幫助開(kāi)發(fā)者構(gòu)建更加強(qiáng)大、靈活的系統(tǒng)。
以上就是C++使用備忘錄模式實(shí)現(xiàn)對(duì)象狀態(tài)保存與恢復(fù)功能的詳細(xì)內(nèi)容,更多關(guān)于C++對(duì)象狀態(tài)保存與恢復(fù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vs code 配置c/c++環(huán)境的詳細(xì)教程(推薦)
這篇文章主要介紹了vs code 配置c/c++環(huán)境的詳細(xì)教程(推薦),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
C語(yǔ)言實(shí)現(xiàn)手寫(xiě)Map(數(shù)組+鏈表+紅黑樹(shù))的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用C語(yǔ)言實(shí)現(xiàn)手寫(xiě)Map(數(shù)組+鏈表+紅黑樹(shù)),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)有一定借鑒價(jià)值,需要的可以參考一下2022-09-09
利用C語(yǔ)言將點(diǎn)分十進(jìn)制的IP字符串轉(zhuǎn)成4個(gè)整數(shù)
這篇文章主要為大家詳細(xì)介紹了如何利用C語(yǔ)言實(shí)現(xiàn)將點(diǎn)分十進(jìn)制的IP字符串轉(zhuǎn)成4個(gè)整數(shù),文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-01-01
C語(yǔ)言系統(tǒng)日期和時(shí)間實(shí)例詳解
我們?cè)趯?xiě)C語(yǔ)言程序的時(shí)候,有的時(shí)候會(huì)用到讀取本機(jī)的時(shí)間和日期,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言系統(tǒng)日期和時(shí)間的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06
C++?shared_ptr智能指針reset()使用示例詳解
這篇文章主要為大家介紹了C++?shared_ptr智能指針reset()使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
c語(yǔ)言實(shí)現(xiàn)向上取整計(jì)算方法
這篇文章主要介紹了c語(yǔ)言實(shí)現(xiàn)向上取整計(jì)算方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
C語(yǔ)言實(shí)現(xiàn)學(xué)生選課系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)學(xué)生選課系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02
C語(yǔ)言實(shí)現(xiàn)實(shí)驗(yàn)設(shè)備管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)實(shí)驗(yàn)設(shè)備管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06

