
//MagicState.java
// 魔法狀態備忘錄
public class MagicState {
    private final int manaLevel;
    private final String spellForm;
    private final String experimentPhase;
    private final long timestamp;
    public MagicState(int manaLevel, String spellForm, String experimentPhase) {
        this.manaLevel = manaLevel;
        this.spellForm = spellForm;
        this.experimentPhase = experimentPhase;
        this.timestamp = System.currentTimeMillis();
    }
    // 只提供給原發器的恢復方法
    protected int getManaLevel() {
        return manaLevel;
    }
    protected String getSpellForm() {
        return spellForm;
    }
    protected String getExperimentPhase() {
        return experimentPhase;
    }
    public long getTimestamp() {
        return timestamp;
    }
    @Override
    public String toString() {
        return String.format("魔法狀態[魔力:%d, 形態:%s, 階段:%s, 時間:%d]",
                           manaLevel, spellForm, experimentPhase, timestamp);
    }
}
//YoungWizard.java
// 年輕法師(原發器)
public class YoungWizard {
    private int manaLevel;
    private String spellForm;
    private String experimentPhase;
    public YoungWizard() {
        this.manaLevel = 100;
        this.spellForm = "人形";
        this.experimentPhase = "準備階段";
    }
    // 創建備忘錄
    public MagicState createMemento() {
        System.out.println("老法師記錄當前狀態...");
        return new MagicState(manaLevel, spellForm, experimentPhase);
    }
    // 從備忘錄恢復狀態
    public void restoreFromMemento(MagicState memento) {
        if (memento != null) {
            this.manaLevel = memento.getManaLevel();
            this.spellForm = memento.getSpellForm();
            this.experimentPhase = memento.getExperimentPhase();
            System.out.println("從備忘錄泡泡中恢復狀態!");
        }
    }
    // 進行魔法實驗
    public void performExperiment(String newForm, String phase) {
        System.out.println("正在施展變形術...");
        this.spellForm = newForm;
        this.experimentPhase = phase;
        this.manaLevel -= 20;
        System.out.println("當前狀態: " + getCurrentState());
    }
    // 消耗魔力
    public void consumeMana(int amount) {
        this.manaLevel -= amount;
        System.out.println("消耗魔力 " + amount + ",當前魔力: " + manaLevel);
    }
    // 獲取當前狀態描述
    public String getCurrentState() {
        return String.format("魔力:%d, 形態:%s, 階段:%s",
                           manaLevel, spellForm, experimentPhase);
    }
    // 顯示當前狀態
    public void showCurrentState() {
        System.out.println("=== 年輕法師當前狀態 ===");
        System.out.println(getCurrentState());
    }
}
//MagicApprentice.java
// 魔法學徒(管理者)
import java.util.*;
public class MagicApprentice {
    private List<MagicState> mementoHistory;
    private String apprenticeName;
    public MagicApprentice(String name) {
        this.apprenticeName = name;
        this.mementoHistory = new ArrayList<>();
    }
    // 保存備忘錄
    public void saveMemento(MagicState memento) {
        mementoHistory.add(memento);
        System.out.println(apprenticeName + " 保存了第 " + mementoHistory.size() + " 個備忘錄泡泡");
    }
    // 獲取最近的備忘錄
    public MagicState getLastMemento() {
        if (mementoHistory.isEmpty()) {
            System.out.println("沒有可用的備忘錄泡泡!");
            return null;
        }
        MagicState memento = mementoHistory.get(mementoHistory.size() - 1);
        System.out.println(apprenticeName + " 取出最近的備忘錄泡泡");
        return memento;
    }
    // 獲取指定索引的備忘錄
    public MagicState getMementoAt(int index) {
        if (index < 0 || index >= mementoHistory.size()) {
            System.out.println("無效的備忘錄索引!");
            return null;
        }
        System.out.println(apprenticeName + " 取出第 " + (index + 1) + " 個備忘錄泡泡");
        return mementoHistory.get(index);
    }
    // 顯示所有備忘錄歷史
    public void showMementoHistory() {
        System.out.println("=== " + apprenticeName + " 的備忘錄歷史 ===");
        if (mementoHistory.isEmpty()) {
            System.out.println("目前沒有保存任何備忘錄");
            return;
        }
        for (int i = 0; i < mementoHistory.size(); i++) {
            System.out.println((i + 1) + ". " + mementoHistory.get(i));
        }
    }
    // 清除所有備忘錄
    public void clearHistory() {
        mementoHistory.clear();
        System.out.println(apprenticeName + " 清除了所有備忘錄泡泡");
    }
    public int getMementoCount() {
        return mementoHistory.size();
    }
}
//MementoPatternExample.java
// 使用範例
public class MementoPatternExample {
    public static void main(String[] args) {
        System.out.println("=== 歡迎來到魔法研究學院 ===\n");
        // 創建角色
        YoungWizard wizard = new YoungWizard();
        MagicApprentice apprentice = new MagicApprentice("學徒艾莉絲");
        // 顯示初始狀態
        wizard.showCurrentState();
        System.out.println();
        // 第一個安全點:保存初始狀態
        MagicState checkpoint1 = wizard.createMemento();
        apprentice.saveMemento(checkpoint1);
        System.out.println();
        // 開始實驗:變形術
        wizard.performExperiment("貓形", "初級變形");
        wizard.consumeMana(10);
        System.out.println();
        // 第二個安全點:保存中間狀態
        MagicState checkpoint2 = wizard.createMemento();
        apprentice.saveMemento(checkpoint2);
        System.out.println();
        // 繼續實驗:高級變形
        wizard.performExperiment("龍形", "高級變形");
        wizard.consumeMana(30);
        System.out.println();
        // 實驗出錯!法師變成了青蛙
        wizard.performExperiment("青蛙", "實驗失敗");
        wizard.consumeMana(20);
        System.out.println("糟糕!實驗失敗了!");
        wizard.showCurrentState();
        System.out.println();
        // 顯示備忘錄歷史
        apprentice.showMementoHistory();
        System.out.println();
        // 恢復到第二個安全點(龍形之前)
        System.out.println("=== 恢復到第二個安全點 ===");
        MagicState restorePoint = apprentice.getMementoAt(1);
        wizard.restoreFromMemento(restorePoint);
        wizard.showCurrentState();
        System.out.println();
        // 或者恢復到最初的安全點
        System.out.println("=== 恢復到初始狀態 ===");
        MagicState initialState = apprentice.getMementoAt(0);
        wizard.restoreFromMemento(initialState);
        wizard.showCurrentState();
        /**output
        === 歡迎來到魔法研究學院 ===
        === 年輕法師當前狀態 ===
        魔力:100, 形態:人形, 階段:準備階段
        老法師記錄當前狀態...
        學徒艾莉絲 保存了第 1 個備忘錄泡泡
        正在施展變形術...
        當前狀態: 魔力:80, 形態:貓形, 階段:初級變形
        消耗魔力 10,當前魔力: 70
        老法師記錄當前狀態...
        學徒艾莉絲 保存了第 2 個備忘錄泡泡
        正在施展變形術...
        當前狀態: 魔力:50, 形態:龍形, 階段:高級變形
        消耗魔力 30,當前魔力: 20
        正在施展變形術...
        當前狀態: 魔力:0, 形態:青蛙, 階段:實驗失敗
        消耗魔力 20,當前魔力: -20
        糟糕!實驗失敗了!
        === 年輕法師當前狀態 ===
        魔力:-20, 形態:青蛙, 階段:實驗失敗
        === 學徒艾莉絲 的備忘錄歷史 ===
        1. 魔法狀態[魔力:100, 形態:人形, 階段:準備階段, 時間:1759838956934]
        2. 魔法狀態[魔力:70, 形態:貓形, 階段:初級變形, 時間:1759838956934]
        === 恢復到第二個安全點 ===
        學徒艾莉絲 取出第 2 個備忘錄泡泡
        從備忘錄泡泡中恢復狀態!
        === 年輕法師當前狀態 ===
        魔力:70, 形態:貓形, 階段:初級變形
        === 恢復到初始狀態 ===
        學徒艾莉絲 取出第 1 個備忘錄泡泡
        從備忘錄泡泡中恢復狀態!
        === 年輕法師當前狀態 ===
        魔力:100, 形態:人形, 階段:準備階段
        */
    }
}
// 魔法狀態備忘錄
class MagicState {
  constructor(manaLevel, spellForm, experimentPhase) {
    this.manaLevel = manaLevel;
    this.spellForm = spellForm;
    this.experimentPhase = experimentPhase;
    this.timestamp = Date.now();
  }
  // 只提供給原發器的恢復方法
  getManaLevel() {
    return this.manaLevel;
  }
  getSpellForm() {
    return this.spellForm;
  }
  getExperimentPhase() {
    return this.experimentPhase;
  }
  getTimestamp() {
    return this.timestamp;
  }
  toString() {
    return `魔法狀態[魔力:${this.manaLevel}, 形態:${this.spellForm}, 階段:${this.experimentPhase}, 時間:${this.timestamp}]`;
  }
}
// 年輕法師(原發器)
class YoungWizard {
  constructor() {
    this.manaLevel = 100;
    this.spellForm = "人形";
    this.experimentPhase = "準備階段";
  }
  // 創建備忘錄
  createMemento() {
    console.log("老法師記錄當前狀態...");
    return new MagicState(this.manaLevel, this.spellForm, this.experimentPhase);
  }
  // 從備忘錄恢復狀態
  restoreFromMemento(memento) {
    if (memento) {
      this.manaLevel = memento.getManaLevel();
      this.spellForm = memento.getSpellForm();
      this.experimentPhase = memento.getExperimentPhase();
      console.log("從備忘錄泡泡中恢復狀態!");
    }
  }
  // 進行魔法實驗
  performExperiment(newForm, phase) {
    console.log("正在施展變形術...");
    this.spellForm = newForm;
    this.experimentPhase = phase;
    this.manaLevel -= 20;
    console.log(`當前狀態: ${this.getCurrentState()}`);
  }
  // 消耗魔力
  consumeMana(amount) {
    this.manaLevel -= amount;
    console.log(`消耗魔力 ${amount},當前魔力: ${this.manaLevel}`);
  }
  // 獲取當前狀態描述
  getCurrentState() {
    return `魔力:${this.manaLevel}, 形態:${this.spellForm}, 階段:${this.experimentPhase}`;
  }
  // 顯示當前狀態
  showCurrentState() {
    console.log("=== 年輕法師當前狀態 ===");
    console.log(this.getCurrentState());
  }
}
// 魔法學徒(管理者)
class MagicApprentice {
  constructor(name) {
    this.apprenticeName = name;
    this.mementoHistory = [];
  }
  // 保存備忘錄
  saveMemento(memento) {
    this.mementoHistory.push(memento);
    console.log(
      `${this.apprenticeName} 保存了第 ${this.mementoHistory.length} 個備忘錄泡泡`
    );
  }
  // 獲取最近的備忘錄
  getLastMemento() {
    if (this.mementoHistory.length === 0) {
      console.log("沒有可用的備忘錄泡泡!");
      return null;
    }
    const memento = this.mementoHistory[this.mementoHistory.length - 1];
    console.log(`${this.apprenticeName} 取出最近的備忘錄泡泡`);
    return memento;
  }
  // 獲取指定索引的備忘錄
  getMementoAt(index) {
    if (index < 0 || index >= this.mementoHistory.length) {
      console.log("無效的備忘錄索引!");
      return null;
    }
    console.log(`${this.apprenticeName} 取出第 ${index + 1} 個備忘錄泡泡`);
    return this.mementoHistory[index];
  }
  // 顯示所有備忘錄歷史
  showMementoHistory() {
    console.log(`=== ${this.apprenticeName} 的備忘錄歷史 ===`);
    if (this.mementoHistory.length === 0) {
      console.log("目前沒有保存任何備忘錄");
      return;
    }
    this.mementoHistory.forEach((memento, index) => {
      console.log(`${index + 1}. ${memento.toString()}`);
    });
  }
  // 清除所有備忘錄
  clearHistory() {
    this.mementoHistory = [];
    console.log(`${this.apprenticeName} 清除了所有備忘錄泡泡`);
  }
  getMementoCount() {
    return this.mementoHistory.length;
  }
}
// 使用範例
console.log("=== 歡迎來到魔法研究學院 ===");
// 創建角色
const wizard = new YoungWizard();
const apprentice = new MagicApprentice("學徒艾莉絲");
// 顯示初始狀態
wizard.showCurrentState();
console.log("");
// 第一個安全點:保存初始狀態
const checkpoint1 = wizard.createMemento();
apprentice.saveMemento(checkpoint1);
console.log("");
// 開始實驗:變形術
wizard.performExperiment("貓形", "初級變形");
wizard.consumeMana(10);
console.log("");
// 第二個安全點:保存中間狀態
const checkpoint2 = wizard.createMemento();
apprentice.saveMemento(checkpoint2);
console.log("");
// 繼續實驗:高級變形
wizard.performExperiment("龍形", "高級變形");
wizard.consumeMana(30);
console.log("");
// 實驗出錯!法師變成了青蛙
wizard.performExperiment("青蛙", "實驗失敗");
wizard.consumeMana(20);
console.log("糟糕!實驗失敗了!");
wizard.showCurrentState();
console.log("");
// 顯示備忘錄歷史
apprentice.showMementoHistory();
console.log("");
// 恢復到第二個安全點(龍形之前)
console.log("=== 恢復到第二個安全點 ===");
const restorePoint = apprentice.getMementoAt(1);
wizard.restoreFromMemento(restorePoint);
wizard.showCurrentState();
console.log("");
// 或者恢復到最初的安全點
console.log("=== 恢復到初始狀態 ===");
const initialState = apprentice.getMementoAt(0);
wizard.restoreFromMemento(initialState);
wizard.showCurrentState();
/** output
=== 歡迎來到魔法研究學院 ===
=== 年輕法師當前狀態 ===
魔力:100, 形態:人形, 階段:準備階段
老法師記錄當前狀態...
學徒艾莉絲 保存了第 1 個備忘錄泡泡
正在施展變形術...
當前狀態: 魔力:80, 形態:貓形, 階段:初級變形
消耗魔力 10,當前魔力: 70
老法師記錄當前狀態...
學徒艾莉絲 保存了第 2 個備忘錄泡泡
正在施展變形術...
當前狀態: 魔力:50, 形態:龍形, 階段:高級變形
消耗魔力 30,當前魔力: 20
正在施展變形術...
當前狀態: 魔力:0, 形態:青蛙, 階段:實驗失敗
消耗魔力 20,當前魔力: -20
糟糕!實驗失敗了!
=== 年輕法師當前狀態 ===
魔力:-20, 形態:青蛙, 階段:實驗失敗
=== 學徒艾莉絲 的備忘錄歷史 ===
1. 魔法狀態[魔力:100, 形態:人形, 階段:準備階段, 時間:1759838956934]
2. 魔法狀態[魔力:70, 形態:貓形, 階段:初級變形, 時間:1759838956934]
=== 恢復到第二個安全點 ===
學徒艾莉絲 取出第 2 個備忘錄泡泡
從備忘錄泡泡中恢復狀態!
=== 年輕法師當前狀態 ===
魔力:70, 形態:貓形, 階段:初級變形
=== 恢復到初始狀態 ===
學徒艾莉絲 取出第 1 個備忘錄泡泡
從備忘錄泡泡中恢復狀態!
=== 年輕法師當前狀態 ===
魔力:100, 形態:人形, 階段:準備階段
 */
Originator(原發器)
YoungWizard 年輕法師就是原發器Memento(備忘錄)
MagicState 魔法狀態就是備忘錄Caretaker(管理者/負責人)
MagicApprentice 魔法學徒就是管理者Memento 設計模式就像我們故事中的時光回溯書記官,透過備忘錄物件來保存和恢復物件的狀態
核心特點:
使用時機: