複製鏈接
請複製以下鏈接發送給好友

備忘錄模式

鎖定
備忘錄模式是一種軟件設計模式:在不破壞封閉的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象恢復到原先保存的狀態。
中文名
備忘錄模式
外文名
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;
}