2018-09-22 22:35:23ios
備忘錄(Memento):在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態。這樣之後就可將該對象恢復到原來保存的狀態。設計模式
Originator(發起人):負責建立一個備忘錄Memento,用以記錄當前時刻它的內部狀態,並可使用備忘錄恢復內部狀態。Originator可根據須要決定Memento存儲Originator的哪些內部狀態。ide
Memento(備忘錄):負責存儲Originator對象的內部狀態,並可防止Originator之外的其它對象訪問備忘錄Memento。備忘錄有兩個接口,Cartaker只能看到備忘錄的窄接口,它只能將備忘錄傳遞給其它對象。Originator能看到一個寬接口,容許它訪問返回到先前狀態所需的全部數據。函數
Caretaker(管理者):負責保存好備忘錄Memento,不能對備忘錄的內容進行操做或者檢查。spa
優勢:設計
1.提供了一種狀態恢復機制,把要保存的細節封裝在了Memento中,使用戶可以方便的回到某個歷史狀態,若是須要更改保存的細節,也不會對客戶端產生影響。rest
2.實現了信息的封裝,使用戶不須要關心保存信息的細節。code
缺點:對象
1.角色狀態須要完整存儲到備忘錄對象中,若是狀態數據不少很大,那麼在資源消耗上,備忘錄對象會很是消耗內存。blog
適用場景:
Memento模式比較適用於功能比較複雜的,但須要維護或記錄屬性歷史的類,或者須要保存的屬性只是衆多屬性中的一小部分時,Originator能夠根據保存的Memento信息還原到前一狀態,有時一些對象的內部信息必須保存在對象之外的地方,可是必須由對象本身讀取,這是使用備忘錄能夠把複雜的對象內部信息對其它的對象屏蔽起來。做用是,當角色的狀態改變的時候,有可能這個狀態無效,這時候就可使用暫時存儲起來的備忘錄將狀態復原。
(都是《大話設計模式》這本書的內容呀)背景:遊戲進度備忘。假設咱們須要保存的遊戲角色的屬性有:藍量、血量、以及攻擊力、防護力四個。
1.Originator類。打遊戲的時候只有角色本身擁有恢復存檔和保存進度的能力
#ifndef ORIGINATOR_H_ #define ORIGINATOR_H_ //這個類在本例中是遊戲角色類 //假設你正在玩某個遊戲,回憶一下,具備存檔和讀取存檔數據的是否是隻有你的遊戲角色呢? #include "Memento.h" #include <string> #include <iostream> class Originator { public: Memento createMemento() { return Memento(m_iLifeValues,m_iMP,m_iATK,m_iDef); //建立一個備忘錄,將當前須要保存的信息導入,並實例化出一個Memento對象 } //從備忘錄中恢復存檔(爲何須要這個函數呢,你想一下,你在存檔以後,下機了,下次再登陸進入遊戲,要恢復存檔,數據必然要從某個地方讀入,因此這個函數是必須的 void restoreMemento(Memento objMemento) { m_iLifeValues = objMemento.getLifeValues(); m_iMP = objMemento.getMP(); m_iATK = objMemento.getATK(); m_iDef = objMemento.getDef(); } //顯示屬性值 void show() const { std::cout << "Name: " << m_strRoleName << " LifeValues:" << m_iLifeValues << " MP:" << m_iMP << " ATK:" << m_iATK << " Def:" << m_iDef <<std::endl; } //設置屬性的初始值 void setInit(const int iLifeValues,const int iMP,const int iATK, const int iDef) { m_iLifeValues = iLifeValues; m_iMP = iMP; m_iATK = iATK; m_iDef = iDef; } //和Boss玩玩,給你一下各項屬性減去100(隨便寫的,因此結果可能出現負值) //返回值爲false,則表示Game over bool beatAMonster() { m_iLifeValues -=100; m_iMP -= 100; m_iATK -=100; m_iDef -=100; if(0>= m_iLifeValues) { return false; } return true; } Originator(const std::string strRoleName) : m_strRoleName(strRoleName){}; ~Originator() = default; private: //遊戲角色的屬性:生命值、魔法值、攻擊力、防護力 int m_iLifeValues{0}; //生命值 int m_iMP{0}; //魔法值 int m_iATK{0}; //攻擊力 int m_iDef{0}; //防護值 std::string m_strRoleName; }; #endif
2.Mementor類。備忘錄,用於保存Originator類內部狀態的外部類
#ifndef MEMENTO_H_ #define MEMENTO_H_ //備忘錄類,負責保存屬性 class Memento { public: //讀取存檔生命值 int getLifeValues() const { return m_iLifeValues; } //讀取魔法存檔值 int getMP() const { return m_iMP; } //讀取攻擊力存檔 int getATK() const { return m_iATK; } //讀取防護力存檔 int getDef() const { return m_iDef; } Memento(const int iLifeValues,const int iMP,const int iATK,const int iDef):m_iLifeValues(iLifeValues),m_iMP(iMP),m_iATK(iATK),m_iDef(iDef){}; Memento(const Memento& objMemento) { m_iLifeValues = objMemento.getLifeValues(); m_iMP = objMemento.getMP(); m_iATK = objMemento.getATK(); m_iDef = objMemento.getDef(); } Memento() = default; ~Memento() = default; private: int m_iLifeValues{0}; //生命值 int m_iMP{0}; //魔法值 int m_iATK{0}; //攻擊力 int m_iDef{0}; //防護力 }; #endif
3.Caretaker類。備忘錄的管理類。
#ifndef CARETAKER_H_ #define CARETAKER_H_ //管理者,這個類用來管理備忘錄,它的做用,就是從加載備忘錄的內容,將其恢復到某個對象 #include "Memento.h" class Caretaker { public: //設置備忘錄 void setMemento(Memento objMemento) { m_Memento = objMemento; } Memento getMemento() { return m_Memento; } private: Memento m_Memento; //持有一個備忘錄對象,它是Caretaker進行備忘錄管理的關鍵 }; #endif
4.client
#include "Caretaker.h" #include "Originator.h" using namespace std; int main(int argc,char *argv[]) { //建立一個遊戲角色 Originator objOriginator("ChongLou"); //設置初始屬性 objOriginator.setInit(100,100,100,100); //保存初始狀態 Caretaker objCaretaker; objCaretaker.setMemento(objOriginator.createMemento()); //顯示初始狀態 objOriginator.show(); //開始打怪 objOriginator.beatAMonster(); //顯示打怪後的屬性 objOriginator.show(); //加載存檔 objOriginator.restoreMemento(objCaretaker.getMemento()); //顯示加載存檔後的屬性 objOriginator.show(); return(1); }