(明日方舟同人文)執行任務篇
阿新 • • 發佈:2022-04-04
備忘錄模式又叫做快照模式,屬於行為型模式。是指使用一個備忘錄物件來儲存另一個物件內部狀態的快照。備忘錄模式的用以是在不破壞封裝的條件下,將一個物件的狀態捕捉住,並外部化,儲存起來,從而可以在將來合適的時候把這個物件還原到儲存起來的狀態。
開發者對這個模式應該很熟悉,我們使用的開發軟體都會有這樣的備忘錄功能。在編輯時按 Ctrl+Z 組合鍵時能撤銷當前操作,使文件恢復到之前的狀態;資料庫也有undo、redo的日誌記錄功能,如果在一個事務內報錯了,可以迴歸到修改之前的資料。
備忘錄模式的UML類圖如下:
由上圖可知備忘錄模式主要涉及到備忘錄(Memento)角色、發起人(Originator)角色和負責人(Caretaker)角色三個角色:
- 發起人(Originator)角色:建立一個含有當前的內部狀態備忘錄物件,使用備忘錄物件儲存其內部狀態
- 備忘錄(Memento)角色:負責儲存好記錄,即發起人角色的內部狀態。備忘錄可以根據發起人物件的判斷來決定儲存多少發起人物件的內部狀態
- 負責人(Caretaker)角色:負責儲存備忘錄物件,不檢查備忘錄物件的內容。一般使用記錄儲存備忘錄物件
遊戲角色例子
遊戲角色有攻擊力和防禦力,在大戰Boss前儲存自身的狀態(攻擊力和防禦力),當大戰Boss 後攻擊力和防禦力下降,從備忘錄物件恢復到大戰前的狀態。
例子的UML類圖:
備忘錄角色:
package com.charon.Memento; /** * @className: Memento * @description: 備忘錄角色 * @author: charon * @create: 2022-04-05 22:43 */ public class Memento { private int vit,def; public Memento(int vit, int def) { this.vit = vit; this.def = def; } public Memento() { } /** * Gets the value of vit * * @return the value of vit */ public int getVit() { return vit; } /** * Gets the value of def * * @return the value of def */ public int getDef() { return def; } }
負責人角色:
package com.charon.Memento; import java.util.ArrayList; import java.util.List; /** * @className: Caretaker * @description: 負責人角色 * @author: charon * @create: 2022-04-05 22:50 */ public class Caretaker { private Memento memento = new Memento(); /** * Gets the value of mementos * * @return the value of mementos */ public Memento getMemento() { return memento; } /** * Sets the mementos * * @param memento memento */ public void setMemento(Memento memento) { this.memento = memento; } }
發起人角色:
package com.charon.Memento;
/**
* @className: GameRole
* @description:
* @author: charon
* @create: 2022-04-05 23:01
*/
public class GameRole {
private int vit,def;
public GameRole(int vit, int def) {
this.vit = vit;
this.def = def;
}
/**
* Gets the value of vit
*
* @return the value of vit
*/
public int getVit() {
return vit;
}
/**
* Sets the vit
*
* @param vit vit
*/
public void setVit(int vit) {
this.vit = vit;
}
/**
* Gets the value of def
*
* @return the value of def
*/
public int getDef() {
return def;
}
/**
* Sets the def
*
* @param def def
*/
public void setDef(int def) {
this.def = def;
}
/**
* 建立備忘錄物件
* @return
*/
public Memento createMemento(){
return new Memento(vit,def);
}
/**
* 從備忘錄物件中恢復gameRole的狀態
* @param memento
*/
public void recoverGameRoleFromMemento(Memento memento){
this.vit = memento.getVit();
this.def = memento.getDef();
}
public void display(){
System.out.println("當前遊戲角色的攻擊力為:" + this.vit + " ;防禦力為:" + this.def);
}
}
測試:
package com.charon.Memento;
/**
* @className: Client
* @description:
* @author: charon
* @create: 2022-04-04 23:00
*/
public class Client {
public static void main(String[] args) {
// 建立遊戲角色
GameRole role = new GameRole(100,100);
System.out.println("大戰前的狀態:");
role.display();
// 儲存當前狀態
Caretaker caretaker = new Caretaker();
caretaker.setMemento(role.createMemento());
System.out.println("開始打boss:");
role.setDef(70);
role.setVit(70);
role.display();
System.out.println("大戰後,使用備忘錄物件恢復到戰前");
role.recoverGameRoleFromMemento(caretaker.getMemento());
System.out.println("恢復後的狀態:");
role.display();
}
}
列印:
大戰前的狀態:
當前遊戲角色的攻擊力為:100 ;防禦力為:100
開始打boss:
當前遊戲角色的攻擊力為:70 ;防禦力為:70
大戰後,使用備忘錄物件恢復到戰前
恢復後的狀態:
當前遊戲角色的攻擊力為:100 ;防禦力為:100
備忘錄模式主要的優點如下:
- 提供了一種可以恢復狀態的機制。當用戶需要時能夠比較方便地將資料恢復到某個歷史的狀態。
- 實現了內部狀態的封裝。除了建立它的發起人之外,其他物件都不能夠訪問這些狀態資訊。
- 簡化了發起人類。發起人不需要管理和儲存其內部狀態的各個備份,所有狀態資訊都儲存在備忘錄中,並由管理者進行管理,這符合單一職責原則。
其主要缺點是:
- 資源消耗大。如果要儲存的內部狀態資訊過多或者特別頻繁,將會佔用比較大的記憶體資源。
備忘錄模式的應用場景
- 需要儲存與恢復資料的場景,如玩遊戲時的中間結果的存檔功能。
- 需要提供一個可回滾操作的場景,如 Word、記事本、Photoshop,Eclipse 等軟體在編輯時按 Ctrl+Z 組合鍵,還有資料庫中事務操作。
備忘錄模式與命令模式的關係
如果涉及到某個物件的可撤銷操作的狀態儲存問題,那麼僅僅使用備忘錄模式是不夠的,應該考慮使用命令模式。
如果在某個系統中使用命令模式時,需要實現命令的撤銷功能,那麼命令模式可以使用備忘錄模式來儲存可撤銷操作的狀態。