《C++新經典設計模式》之第18章 備忘錄模式

《C++新經典設計模式》之第18章 備忘錄模式

        • 備忘錄模式.cpp

備忘錄模式.cpp
#include <iostream>
#include <vector>
#include <memory>
using namespace std;// 保存對象內部狀態,必要時恢復
// 在不破壞封裝性的前提下,捕獲對象的內部狀態并保存,之后可將對象恢復到原先保存的狀態
// 3種角色
// Originator(原發器),普通業務類,可以創建備忘錄用于保存其當前的內部狀態,之后用備忘錄恢復內部狀態
// Memento(備忘錄),存儲原發器對象某個瞬間的內部狀態
// CareTaker(負責人/管理者),保存和傳遞備忘錄,不知道備忘錄細節,不能檢查或操作備忘錄namespace ns1
{class FighterMemento // 玩家主角相關的備忘錄類{friend class Fighter; // 友元類Fighter可以訪問本類的私有成員函數// 玩家主角類中要保存起來的數據,就放到這里來int m_life;   // 生命值int m_magic;  // 魔法值int m_attack; // 攻擊力private: // 構造函數,用private修飾以防止在外部被隨意創建FighterMemento(int life, int magic, int attack) : m_life(life), m_magic(magic), m_attack(attack) {}private: // 提供一些供Fighter類來訪問的接口,用private修飾防止被任意類訪問int getLife() const { return m_life; }void setLife(int life) { m_life = life; }int getMagic() const { return m_magic; }void setMagic(int magic) { m_magic = magic; }int getAttack() const { return m_attack; }void setAttack(int attack) { m_attack = attack; }};class Fighter     // 玩家主角類{                 // 角色屬性int m_life;   // 生命值int m_magic;  // 魔法值int m_attack; // 攻擊力public:Fighter(int life, int magic, int attack) : m_life(life), m_magic(magic), m_attack(attack) {}public: // 將玩家數據寫入備忘錄(創建備忘錄,并在其中存儲了當前狀態)shared_ptr<FighterMemento> createMomento() const{shared_ptr<FighterMemento> back(new FighterMemento(m_life, m_magic, m_attack));return back;// return make_shared<FighterMemento>(m_life, m_magic, m_attack);}void restoreMomento(const shared_ptr<FighterMemento> &pfm) // 從備忘錄中恢復玩家數據{m_life = pfm->m_life; // 友元類m_magic = pfm->getMagic();m_attack = pfm->getAttack();}void setToDead() { m_life = 0; } // 為測試目的引入的接口,設置玩家的生命值為0(玩家死亡)void displayInfo() const         // 用于輸出一些信息{cout << "The player's current HP, magic and attack power are respectively " << m_life << ", " << m_magic << ", " << m_attack << endl;}};class FCareTaker // 管理者(負責人)類{shared_ptr<FighterMemento> m_pfm; // 指向備忘錄對象的指針public:FCareTaker(const shared_ptr<FighterMemento> &ptmpfm = nullptr) : m_pfm(ptmpfm) {} // 形參是指向備忘錄對象的指針shared_ptr<FighterMemento> getMemento() const { return m_pfm; }                   // 獲取指向備忘錄對象的指針void setMemento(const shared_ptr<FighterMemento> &ptmpfm) { m_pfm = ptmpfm; }     // 保存指向備忘錄對象的指針};class FCareTaker2 // 支持多個快照的負責人(管理者)類{vector<shared_ptr<FighterMemento>> m_pfmContainer; // 存儲備忘錄對象指針的容器public:void push(const shared_ptr<FighterMemento> &ptmpfm) { m_pfmContainer.emplace_back(ptmpfm); } // 保存指向備忘錄對象的指針shared_ptr<FighterMemento> pop(){if (m_pfmContainer.empty())return nullptr;return m_pfmContainer.back();}shared_ptr<FighterMemento> getMemento(int index) const // 獲取指向備忘錄對象的指針{if (index >= 0 && index < m_pfmContainer.size())return m_pfmContainer[index];return nullptr;}};
}int main()
{
#if 0using namespace ns1;shared_ptr<Fighter> p_fighter(new Fighter(800, 200, 300));// (1)顯示玩家主角在與BOSS戰斗之前的信息p_fighter->displayInfo();// (2)為玩家主角類對象創建一個備忘錄對象(其中保存了當前主角類對象中的必要信息)shared_ptr<FighterMemento> p_fighterMemo = p_fighter->createMomento();// (3)玩家與BOSS開始戰斗cout << "The protagonist of the player and BOSS began to fight fiercely------" << endl;p_fighter->setToDead();   // 玩家主角在與BOSS戰斗中,生命值最終變成0而死亡(被BOSS擊敗)p_fighter->displayInfo(); // 顯示玩家主角在與BOSS戰斗之后的信息// (4)因為在與BOSS戰斗之前已經通過NPC保存了游戲進度,這里模擬載入游戲進度,恢復玩家主角類對象的數據,讓其可以與BOSS再次戰斗cout << "Players recover their information through memos------" << endl;p_fighter->restoreMomento(p_fighterMemo);p_fighter->displayInfo(); // 顯示玩家主角通過備忘錄恢復到戰斗之前的信息
#endif#if 0using namespace ns1;shared_ptr<Fighter> p_fighter(new Fighter(800, 200, 300));// (1)顯示玩家主角在與BOSS戰斗之前的信息p_fighter->displayInfo();// (2)為玩家主角類對象創建一個備忘錄對象(其中保存了當前主角類對象中的必要信息)shared_ptr<FCareTaker> pfcaretaker(new FCareTaker(p_fighter->createMomento()));// (3)玩家與BOSS開始戰斗cout << "The protagonist of the player and BOSS began to fight fiercely------" << endl;p_fighter->setToDead();   // 玩家主角在與BOSS戰斗中,生命值最終變成0而死亡(被BOSS擊敗)p_fighter->displayInfo(); // 顯示玩家主角在與BOSS戰斗之后的信息// (4)因為在與BOSS戰斗之前已經通過NPC保存了游戲進度,這里模擬載入游戲進度,恢復玩家主角類對象的數據,讓其可以與BOSS再次戰斗cout << "Players recover their information through memos------" << endl;p_fighter->restoreMomento(pfcaretaker->getMemento());p_fighter->displayInfo(); // 顯示玩家主角通過備忘錄恢復到戰斗之前的信息
#endif#if 1using namespace ns1;shared_ptr<Fighter> p_fighter2(new Fighter(800, 200, 300));shared_ptr<FCareTaker2> pfcaretaker2(new FCareTaker2());pfcaretaker2->push(p_fighter2->createMomento()); // 做第一次快照嗎,此快照玩家生命值為800p_fighter2->setToDead();                         // 改變玩家主角的生命值pfcaretaker2->push(p_fighter2->createMomento()); // 做第二次快照,此快照玩家生命值為0p_fighter2->displayInfo();                       // 玩家主角生命值應該為0cout << "------------------" << endl;// 當前玩家生命值為0,恢復第一次快照,也就是恢復玩家生命值為800p_fighter2->restoreMomento(pfcaretaker2->getMemento(0));p_fighter2->displayInfo(); // 玩家主角生命值應該恢復為800
#endifcout << "Over!\n";return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/210172.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/210172.shtml
英文地址,請注明出處:http://en.pswp.cn/news/210172.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

(C)一些題11

1. #include<stdio.h> #include<string.h> void main() { char *s1"ABCDEF"&#xff0c;*s2"aB"&#xff1b; s1; s2; puts(s1)&#xff1b; puts(s2)&#xff1b; printf("%d\n",strcmp(s1,s2))&#xff1b; } 答案&#xff1…

【密碼學引論】認證

認證是許多應用系統中安全保護的第一道設防認證和加密的區別&#xff1a;加密用來確保數據的保密性&#xff0c;而認證用來確保報文發送者和接受者的真實性和報文的完整性。認證和數字簽名的區別&#xff1a; 認證總是基于某種收發雙方共享的保密數據來認證被鑒別對象的真實性&…

關于linux開機自啟動

1、系統啟動流程 2、 init、 inittab、 init.d、 rcx.d /etc/inittab是Linux系統中的一個配置文件&#xff0c;用于定義系統的運行級別和相應的操作。其語法格式如下&#xff1a; 標簽&#xff1a;運行級別&#xff1a;操作&#xff1a;進程 label:runlevel:action:process下面…

每天一點python——day90

#每天一點Python——90 #類的創建 創建類的語法&#xff1a; class 類名&#xff1a;pass【縮進之后寫類里面的內容】 [類里面寫什么沒有想好之前&#xff0c;可以用pass進行占位.可以不報錯]#演示&#xff1a; class Lei:pass #以上就上一個類被創建的樣例注意事項&#xff1a…

PHP基礎 - 注釋變量

一. 語言開始標識 在PHP中,文件的開頭需要使用語言開始標識來指定該文件是PHP代碼。標識通常為"<?php",也可以是"<?",但建議使用"<?php"以確保代碼的兼容性和可讀性。 <?php // PHP代碼從這里開始寫 二. PHP注釋 注釋是用…

[英語學習][11][Word Power Made Easy]的精讀與翻譯優化

[序言] 這次翻譯, 譯者有點點水平. 有些比較難表達的, 都能正確地翻譯出來. 但有點很奇怪, 難的地方譯者翻譯正確, 容易的地方又錯了. [英文學習的目標] 提升自身的英語水平, 對日后編程技能的提升有很大幫助. 希望大家這次能學到東西, 同時加入我的社區討論與交流英語相關的…

遇到這個問題怎么辦

1. 問題現象 話說近日博主的團隊中&#xff0c;有一個小盆友遇到了一個問題&#xff0c;即使用RSA進行加解密的時候&#xff0c;拋異常了&#xff1a; java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLeng…

高防CDN:在保障服務器與網站成本的角度的智慧選擇

隨著網絡攻擊的不斷升級和演變&#xff0c;保障服務器與網站安全成為了企業不可忽視的重要問題。高防CDN&#xff08;內容分發網絡&#xff09;技術應運而生&#xff0c;為服務器與網站的穩定運行提供了全面而有效的保護。本文將從服務器與網站成本的角度深入分析高防CDN在降低…

【Python】Faker庫詳解:創建測試數據輕而易舉

Python Faker庫詳解&#xff1a;創建測試數據輕而易舉 在軟件開發和測試過程中&#xff0c;通常需要大量的測試數據來模擬真實環境。Python的Faker庫為開發者提供了一個方便、靈活且強大的工具&#xff0c;用于生成各種虛構數據。本文將深入介紹Faker庫&#xff0c;演示其基本…

十一、了解分布式計算

1、什么是&#xff08;數據&#xff09;計算&#xff1f; 2、分布式(數據)計算 &#xff08;1&#xff09;概念 顧名思義&#xff0c;分布式計算&#xff0c;即以分布式的形式完成數據的統計&#xff0c;得到需要的結果。 分布式數據計算&#xff0c;顧名思義&#xff0c;就是…

c語言選擇排序總結(詳解)

選擇排序cpp文件項目結構截圖 項目cpp文件截圖 項目具體代碼截圖 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <math.h> #include <iostream> #include <string.h> #include <time.h> #include &…

Java發展史

Java發展史 Java歷史的幾個重要節點&#xff1a; 1990&#xff0c;Sun公司啟動了一個名為“綠色計劃”的項目&#xff0c;由James Gosling等領導&#xff0c;目標是開發一種可以在機頂盒等消費性電子產品上運行的程序架構。這個計劃產生了Java的前身&#xff1a;Oak&#xff…

Java八股文面試全套真題【含答案】-XML篇

XML 是什么&#xff1f;它的全稱是什么&#xff1f; 答案&#xff1a;XML&#xff08;可擴展標記語言&#xff09;是一種用于描述數據的標記語言&#xff0c;用于存儲和交換結構化的信息。XML 的全稱是 eXtensible Markup Language。XML 和 HTML 有什么區別&#xff1f; 答案&a…

看圖學源碼 之 ConcurrentHashMap put、get、remove、clear、擴容等相關方法的源碼分析

ConcurrentHashMap 引入 HashMap 的弊端 多線程下是不安全的&#xff0c;是有死循環的 JDK1.7 的時候會使用頭插法將新的節點增加到頭部&#xff0c;那么就會造成鏈表翻轉成為了閉環&#xff0c;就是所謂的死循環。 JDK1.8之后使用的是尾插法&#xff0c;因此不會造成環形鏈…

京東數據運營:京東API接口有哪些?京東數據如何采集調用?

市場分析對于電商品牌來說非常重要&#xff0c;它可以幫助電商品牌更好地理解市場&#xff0c;把握市場機會&#xff0c;以及制定有效的產品定價、產品營銷策略等等。 結合市場中可以幫助品牌方做市場分析的電商數據分析工具——鯨參謀電商數據分析平臺&#xff0c;我們一起具體…

在Mac上安裝Windows應用程序的簡便方法:CrossOver for Mac

對于許多Mac用戶來說&#xff0c;有時候他們可能需要使用一些只有在Windows上才能找到的應用程序。以前&#xff0c;解決這個問題的方法是通過安裝Windows虛擬機或使用雙系統來在Mac上運行Windows應用程序。但這些方法需要額外的硬件資源和時間來配置&#xff0c;并且可能會導致…

IOT安全學習路標

1. 物聯網基礎知識 首先&#xff0c;你需要建立堅實的物聯網基礎知識&#xff0c;包括IoT的架構和組件&#xff0c;傳感器和設備的連接和通信技術&#xff0c;云端和邊緣計算等。 2. 通信和網絡安全 學習關于物聯網通信和網絡安全的基礎知識&#xff0c;包括加密和認證技術、…

通俗解釋一下“強靜態類型”

我寫軟件已經有 20 多年了&#xff0c;隨著時間的推移&#xff0c;我越來越確信強靜態類型不僅是一個好主意&#xff0c;而且幾乎總是正確的選擇。 非類型化語言(或語言變體)肯定有用途&#xff0c;例如&#xff0c;當使用 REPL 時&#xff0c;或者在已經無可救藥的無類型環境(…

有什么進銷存軟件能對接微信小程序?

有什么進銷存軟件能對接微信小程序&#xff1f; 據我所知&#xff0c;很多進銷存軟件都有配套的微信小程序吧。 以我們現在用的這個為例&#xff0c;這也是同行推薦過來的&#xff0c;很好用&#xff0c;而且性價比很高—— 在線平臺&#xff0c;無需下載APP&#xff0c;搭載…

C語言實戰演練之跳動的愛心C語言版

跳 動 的 愛 心 - LOVE - 完整程序 #include <stdio.h> #include <math.h> #include <windows.h> #include <tchar.h> float f(float x, float y, float z) {float a x * x 9.0f / 4.0f * y * y z * z - 1;return a * a * a - x * x * z * z …