跳至主要內容

备忘录模式

约 288 字

备忘录模式

核心思想

备忘录模式允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。

典型用例

存档和加载

在游戏开发中,备忘录模式可以用于保存游戏的当前状态(如角色位置、分数、物品等),并在需要时加载这些状态。

// npm run code src/code/design-pattern/memento/archive-load.ts

export {};

// 备忘录类
class Memento {
    constructor(private state: GameState) {}

    getState(): GameState {
        return this.state;
    }
}

// 发起人类
class GameOriginator {
    private state: GameState;

    constructor(state: GameState) {
        this.state = state;
    }

    save(): Memento {
        return new Memento(this.state);
    }

    restore(memento: Memento): void {
        this.state = memento.getState();
    }

    setState(state: GameState): void {
        this.state = state;
    }

    getState(): GameState {
        return this.state;
    }
}

// 游戏状态
interface GameState {
    level: number;
    score: number;
    // 可以添加更多的游戏相关状态
}

// 负责保存和恢复备忘录的状态管理者类
class GameStateManager {
    private mementos: Memento[] = [];

    addMemento(memento: Memento): void {
        this.mementos.push(memento);
    }

    getMemento(index: number): Memento {
        return this.mementos[index];
    }
}

const game = new GameOriginator({ level: 1, score: 100 });
const manager = new GameStateManager();

// 游戏进展,保存状态
game.setState({ level: 2, score: 200 });
manager.addMemento(game.save());

// 再次游戏进展,保存状态
game.setState({ level: 3, score: 300 });
manager.addMemento(game.save());

// 加载之前的游戏状态
game.restore(manager.getMemento(0));
console.log(game.getState()); // 输出: { level: 2, score: 200 }

撤销和重做

备忘录模式可以用于实现撤销和重做功能,通过保存对象的状态,可以在需要时恢复到之前的状态。

// npm run code src/code/design-pattern/memento/undo-and-redo.ts

export {};

class Memento {
    private state: string;

    constructor(state: string) {
        this.state = state;
    }

    getState(): string {
        return this.state;
    }
}

class Originator {
    private state!: string;

    setState(state: string) {
        this.state = state;
    }

    getState(): string {
        return this.state;
    }

    saveStateToMemento(): Memento {
        return new Memento(this.state);
    }

    getStateFromMemento(memento: Memento) {
        this.state = memento.getState();
    }
}

class Caretaker {
    private mementoList: Memento[] = [];
    private current: number = -1;

    add(state: Memento) {
        this.mementoList.push(state);
        this.current++;
        this.mementoList.splice(this.current + 1);
    }

    undo(): Memento | undefined {
        if (this.current > 0) {
            this.current--;
            return this.mementoList[this.current];
        }
        return undefined;
    }

    redo(): Memento | undefined {
        if (this.current < this.mementoList.length - 1) {
            this.current++;
            return this.mementoList[this.current];
        }
        return undefined;
    }
}

let originator = new Originator();
let caretaker = new Caretaker();

originator.setState('State #1');
caretaker.add(originator.saveStateToMemento());

originator.setState('State #2');
caretaker.add(originator.saveStateToMemento());

// 撤销到上一状态
let undoMemento = caretaker.undo();
if (undoMemento) originator.getStateFromMemento(undoMemento);

console.log("Current State: " + originator.getState());

// 重做到下一状态
let redoMemento = caretaker.redo();
if (redoMemento) originator.getStateFromMemento(redoMemento);

console.log("Current State: " + originator.getState());

事务回滚

在数据库事务处理或业务流程中,如果操作失败或需要回滚,可以使用备忘录模式来恢复到事务开始之前的状态。

// npm run code src/code/design-pattern/memento/transaction-rollback.ts

export {};

class Memento {
    private state: any;

    constructor(state: any) {
        this.state = state;
    }

    getState(): any {
        return this.state;
    }
}

class Originator {
    private state: any;

    setState(state: any) {
        this.state = state;
    }

    getState(): any {
        return this.state;
    }

    saveStateToMemento(): Memento {
        return new Memento(this.state);
    }

    restoreStateFromMemento(memento: Memento) {
        this.state = memento.getState();
    }
}

class Caretaker {
    private memento: Memento | null = null;

    backupState(originator: Originator) {
        this.memento = originator.saveStateToMemento();
    }

    rollbackState(originator: Originator) {
        if (this.memento) {
            originator.restoreStateFromMemento(this.memento);
        }
    }
}

let originator = new Originator();
let caretaker = new Caretaker();

// 初始状态
originator.setState({ data: 'Initial State' });
console.log("Initial State:", originator.getState());

// 备份状态
caretaker.backupState(originator);

try {
    // 尝试更改状态
    originator.setState({ data: 'Changed State' });
    console.log("Changed State:", originator.getState());

    // 模拟操作失败,抛出错误
    throw new Error("Operation failed");

} catch (error: any) {
    console.log("Error occurred:", error.message);
    // 回滚到之前的状态
    caretaker.rollbackState(originator);
    console.log("State after rollback:", originator.getState());
}

对象状态的快照

在监控或审计系统中,备忘录模式可以用来记录系统的关键状态,以便将来进行分析或回溯。

// npm run code src/code/design-pattern/memento/object-snapshot.ts

export {};

class Memento {
    private state: any;

    constructor(state: any) {
        this.state = state;
    }

    getState(): any {
        return this.state;
    }
}

class Originator {
    private state: any;

    setState(state: any) {
        this.state = state;
    }

    getState(): any {
        return this.state;
    }

    saveStateToMemento(): Memento {
        return new Memento(this.state);
    }

    restoreStateFromMemento(memento: Memento) {
        this.state = memento.getState();
    }
}

class Caretaker {
    private mementos: Memento[] = [];

    addMemento(memento: Memento) {
        this.mementos.push(memento);
    }

    getMemento(index: number): Memento | null {
        if (index >= 0 && index < this.mementos.length) {
            return this.mementos[index];
        }
        return null;
    }
}

let originator = new Originator();
let caretaker = new Caretaker();

// 设置并保存第一个状态
originator.setState({ data: 'State 1' });
caretaker.addMemento(originator.saveStateToMemento());

// 设置并保存第二个状态
originator.setState({ data: 'State 2' });
caretaker.addMemento(originator.saveStateToMemento());

// 检索和打印保存的状态
let savedState1 = caretaker.getMemento(0)?.getState();
console.log("Saved State 1:", savedState1);

let savedState2 = caretaker.getMemento(1)?.getState();
console.log("Saved State 2:", savedState2);

上次编辑于: