1.定義:
備忘錄模式(Memento Pattern)保存一個對象的某個狀態(tài)逛艰,以便在適當(dāng)?shù)臅r候恢復(fù)對象家坎。備忘錄模式屬于行為型模式焦除。
2.介紹
介紹
意圖:在不破壞封裝性的前提下尽楔,捕獲一個對象的內(nèi)部狀態(tài)繁涂,并在該對象之外保存這個狀態(tài)盹靴。
主要解決:所謂備忘錄模式就是在不破壞封裝的前提下炸茧,捕獲一個對象的內(nèi)部狀態(tài)帆疟,并在該對象之外保存這個狀態(tài),這樣可以在以后將對象恢復(fù)到原先保存的狀態(tài)宇立。
何時使用:很多時候我們總是需要記錄一個對象的內(nèi)部狀態(tài)踪宠,這樣做的目的就是為了允許用戶取消不確定或者錯誤的操作,能夠恢復(fù)到他原先的狀態(tài)妈嘹,使得他有"后悔藥"可吃柳琢。
如何解決:通過一個備忘錄類專門存儲對象狀態(tài)。
關(guān)鍵代碼:客戶不與備忘錄類耦合润脸,與備忘錄管理類耦合柬脸。
應(yīng)用實例: 1、后悔藥毙驯。 2倒堕、打游戲時的存檔。 3爆价、Windows 里的 ctri + z垦巴。 4、IE 中的后退铭段。 4骤宣、數(shù)據(jù)庫的事務(wù)管理。
優(yōu)點: 1序愚、給用戶提供了一種可以恢復(fù)狀態(tài)的機(jī)制憔披,可以使用戶能夠比較方便地回到某個歷史的狀態(tài)。 2爸吮、實現(xiàn)了信息的封裝芬膝,使得用戶不需要關(guān)心狀態(tài)的保存細(xì)節(jié)。
缺點:消耗資源形娇。如果類的成員變量過多锰霜,勢必會占用比較大的資源,而且每一次保存都會消耗一定的內(nèi)存埂软。
使用場景: 1锈遥、需要保存/恢復(fù)數(shù)據(jù)的相關(guān)狀態(tài)場景纫事。 2勘畔、提供一個可回滾的操作。
注意事項: 1丽惶、為了符合迪米特原則炫七,還要增加一個管理備忘錄的類。 2钾唬、為了節(jié)約內(nèi)存万哪,可使用原型模式+備忘錄模式侠驯。
3.UML結(jié)構(gòu)
4.DEMO(本文以游戲存檔為例)
1.新建一個備忘錄類RoleStateMemento
package org.example.memento;
/**
* @author yzh
* @date 2021/5/7 15:45
**/
public class RoleStateMemento {
private int vit;
private int attack;
private int defence;
public RoleStateMemento(int vit, int attack, int defence) {
this.vit = vit;
this.attack = attack;
this.defence = defence;
}
public RoleStateMemento() {
}
public int getVit() {
return vit;
}
public void setVit(int vit) {
this.vit = vit;
}
public int getAttack() {
return attack;
}
public void setAttack(int attack) {
this.attack = attack;
}
public int getDefence() {
return defence;
}
public void setDefence(int defence) {
this.defence = defence;
}
}
2.新建一個備忘錄管理類,用于管理備忘錄
package org.example.memento;
/**
* @author yzh
* @date 2021/5/7 15:51
**/
public class RoleStateCaretaker {
private RoleStateMemento roleStateMemento;
public RoleStateMemento getRoleStateMemento() {
return roleStateMemento;
}
public void setRoleStateMemento(RoleStateMemento roleStateMemento) {
this.roleStateMemento = roleStateMemento;
}
}
3.新建一個發(fā)起人類RoleState
package org.example.memento;
/**
* @author yzh
* @date 2021/5/7 15:43
**/
public class RoleState {
private int vit;
private int attack;
private int defence;
//初始化
public RoleState() {
vit=100;
attack=100;
defence=100;
}
//讀檔
public void recoveryState(RoleStateMemento roleStateMemento){
this.vit=roleStateMemento.getVit();
this.attack=roleStateMemento.getAttack();
this.defence=roleStateMemento.getDefence();
}
//存檔
public RoleStateMemento saveState(){
return new RoleStateMemento(vit,attack,defence);
}
//戰(zhàn)斗后血量攻擊防御清0
public void fight(){
vit=0;
attack=0;
defence=0;
}
//展示角色當(dāng)前狀態(tài)
public void show(){
System.out.println("vit="+vit);
System.out.println("attack="+attack);
System.out.println("defence="+defence);
}
}
4.新建客戶端類
package org.example.memento;
/**
* @author yzh
* @date 2021/5/7 15:31
**/
public class Client {
public static void main(String[] args) {
//新建角色
RoleState roleState = new RoleState();
//新建角色血量攻擊防御都為100
roleState.show();
//創(chuàng)建備忘錄管理者并管理當(dāng)前游戲角色狀態(tài)
RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
roleStateCaretaker.setRoleStateMemento(roleState.saveState());
//游戲角色參與戰(zhàn)斗,戰(zhàn)斗失敗,屬性清0
roleState.fight();
roleState.show();
//恢復(fù)檔案
roleState.recoveryState(roleStateCaretaker.getRoleStateMemento());
roleState.show();
}
}