備忘錄模式

備忘錄模式是一種軟體設計模式:在不破壞封閉的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象恢復到原先保存的狀態。

基本介紹

  • 中文名:備忘錄模式
  • 外文名:Memento Pattern
  • 亦稱:快照模式
  • 屬於:行為模式
基本介紹,舉例說明,

基本介紹

備忘錄模式(Memento Pattern)又叫做快照模式(Snapshot Pattern)或Token模式,是GoF的23種設計模式之一,屬於行為模式。
備忘錄模式備忘錄模式
定義:在不破壞封閉的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象恢復到原先保存的狀態。
涉及角色
1.Originator(發起人):負責創建一個備忘錄Memento,用以記錄當前時刻自身的內部狀態,並可使用備忘錄恢復內部狀態。Originator可以根據需要決定Memento存儲自己的哪些內部狀態。
2.Memento(備忘錄):負責存儲Originator對象的內部狀態,並可以防止Originator以外的其他對象訪問備忘錄。備忘錄有兩個接口:Caretaker只能看到備忘錄的窄接口,他只能將備忘錄傳遞給其他對象。Originator卻可看到備忘錄的寬接口,允許它訪問返回到先前狀態所需要的所有數據。
3.Caretaker(管理者):負責備忘錄Memento,不能對Memento的內容進行訪問或者操作。
備忘錄模式的優點和缺點
一、備忘錄模式的優點
1、有時一些發起人對象的內部信息必須保存在發起人對象以外的地方,但是必須要由發起人對象自己讀取,這時,
使用備忘錄模式可以把複雜的發起人內部信息對其他的對象禁止起來,從而可以恰當地保持封裝的邊界。
2、本模式簡化了發起人類。發起人不再需要管理和保存其內部狀態的一個個版本,客戶端可以自行管理他們所需
要的這些狀態的版本。
3、當發起人角色的狀態改變的時候,有可能這個狀態無效,這時候就可以使用暫時存儲起來的備忘錄將狀態復原。
二、備忘錄模式的缺點:
1、如果發起人角色的狀態需要完整地存儲到備忘錄對象中,那么在資源消耗上面備忘錄對象會很昂貴。
2、當負責人角色將一個備忘錄 存儲起來的時候,負責人可能並不知道這個狀態會占用多大的存儲空間,從而無法提醒用戶一個操作是否很昂貴。
3、當發起人角色的狀態改變的時候,有可能這個協定無效。如果狀態改變的成功率不高的話,不如採取“假如”協定模式。

舉例說明

以保存遊戲進度為例,在遊戲角色大戰Boss前將該角色的狀態存儲,與Boss作戰后角色的各項能力會下降,如果沒有通關,則可利用備忘錄進行恢復到戰前狀態。
遊戲角色類
package com.zyh.designpattern.memento;public class PlayRole {private int vitality;private int aggressivity;private int defencivity;public PlayRole(int vitality, int aggressivity, int defencivity) {super();this.vitality = vitality;this.aggressivity = aggressivity;this.defencivity = defencivity;}public PlayRole() {}public int getVitality() {return vitality;}public void setVitality(int vitality) {this.vitality = vitality;}public int getAggressivity() {return aggressivity;}public void setAggressivity(int aggressivity) {this.aggressivity = aggressivity;}public int getDefencivity() {return defencivity;}public void setDefencivity(int defencivity) {this.defencivity = defencivity;}public RoleMemento createMemento() {RoleMemento memento = new RoleMemento();memento.setAggressivity(aggressivity);memento.setDefencivity(defencivity);memento.setVitality(vitality);return memento;}public void setMemento(RoleMemento memento) {this.aggressivity = memento.getAggressivity();this.defencivity = memento.getDefencivity();this.vitality = memento.getVitality();}public void showState() {System.out.println("攻擊力:" + this.aggressivity + "|防禦力:" + this.defencivity+ "|生命力:" + this.vitality);}}
備忘錄類:
package com.zyh.designpattern.memento;public class RoleMemento {private int vitality;private int aggressivity;private int defencivity;public int getVitality() {return vitality;}public void setVitality(int vitality) {this.vitality = vitality;}public int getAggressivity() {return aggressivity;}public void setAggressivity(int aggressivity) {this.aggressivity = aggressivity;}public int getDefencivity() {return defencivity;}public void setDefencivity(int defencivity) {this.defencivity = defencivity;}}
管理者類:
package com.zyh.designpattern.memento;public class Caretaker {RoleMemento memento;public RoleMemento getMemento() {return memento;}public void setMemento(RoleMemento memento) {this.memento = memento;}}
客戶端:
package com.zyh.designpattern.memento;public class Client {public static void main(String[] args) {// 測試程式// 新建角色PlayRole role = new PlayRole(100, 100, 100);// 新建管理者Caretaker taker = new Caretaker();// 角色初始狀態System.out.println("遊戲剛開始,角色各屬性:");role.showState();// 利用備忘錄模式保存當前狀態System.out.println("\n【保存遊戲狀態!】\n");taker.setMemento(role.createMemento());role.setAggressivity(20);role.setDefencivity(30);role.setVitality(0);// 大戰過後,角色能力值下降System.out.println("與Boss對戰後,角色各項能力已大大下降:");role.showState();// 恢復保存的角色狀態role.setMemento(taker.getMemento());System.out.println("\n【恢復保存的角色狀態!】");System.out.println("\n恢復后角色的當前狀態:");role.showState();}}
C++代碼實現:
#include <iostream>#include <string>using namespace std;//備忘者類備份發起者的狀態class Memento{public: //構造的時候備份數據 Memento(string state):_state(state){}; string _state;};//發起者類備份自己的狀態class Originator{public: //建立備份 Memento* createBackups(){ return new Memento(_state); } //恢復備份內容 void restoreBackups(Memento* memento){ _state = memento->_state; } //顯示狀態 void show() { cout<<_state<<endl; } string _state;};//管理者類管理備份class Caretaker{public: //得到備份 Memento* getMemento(){ return _memento; } //設定備份 void setMemento(Memento* memento){ _memento = memento; } Memento *_memento;};//客戶端代碼#include "Memento.h"int main(void){ //設定和顯示狀態 Originator o; o._state = "ON"; o.show(); //創建備份 Memento* m = o.createBackups(); //管理備份 Caretaker c; c.setMemento(m); //設定和顯示狀態 o._state = "OFF"; o.show(); //恢復備份 m = c.getMemento(); o.restoreBackups(m); //顯示狀態 o.show(); getchar(); return 0;}

相關詞條

熱門詞條

聯絡我們