首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

設計模式實作系列(十九):Memento 備忘錄模式 - 安全捕獲與恢復物件狀態

     編輯:關於C++

模式意圖

在不破壞封裝性的前提下,捕獲一個物件的內部狀態,並在該物件之外保存這個狀態,以便日後將該物件恢復到原先保存的狀態。

UML 結構圖

Memento Pattern UML

核心解析:窄介面與寬介面

Memento 模式關鍵在於介面權限控制:

  • 寬介面: 公開所有狀態存取方法,任何物件皆可讀寫,破壞封裝。
  • 窄介面: 僅暴露給 Originator(發起人),透過 friend 關鍵字限制存取權,確保只有發起人能建立、恢復備忘錄。

本實作採用窄介面:Memento 所有成員為 private,並宣告 Originator 為 friend,外部物件(如 Caretaker 管理者)僅能持有不透明的 Memento*,無法窺探內部狀態。

C++ 完整實作

1. Memento.h

#ifndef MEMENTO_H
#define MEMENTO_H

#include <string>
typedef std::string State;

class Memento;

class Originator {
public:
    Originator(const State& rState);
    Originator();
    ~Originator();

    Memento* CreateMemento();      // 建立備忘錄
    void SetMemento(Memento* pMemento); // 從備忘錄恢復
    State GetState() const;
    void SetState(const State& rState);
    void PrintState() const;

private:
    State m_State;
};

// 窄介面:所有成員私有,僅 Originator 可存取
class Memento {
private:
    friend class Originator;
    Memento(const State& rState);
    void SetState(const State& rState);
    State GetState() const;
    State m_State;
};

#endif

2. Memento.cpp

#include "Memento.h"
#include <iostream>

Originator::Originator() {}
Originator::Originator(const State& rState) : m_State(rState) {}
Originator::~Originator() {}

State Originator::GetState() const { return m_State; }
void Originator::SetState(const State& rState) { m_State = rState; }

Memento* Originator::CreateMemento() {
    return new Memento(m_State);
}

void Originator::SetMemento(Memento* pMemento) {
    if (pMemento) m_State = pMemento->GetState();
}

void Originator::PrintState() const {
    std::cout << "State = " << m_State << std::endl;
}

Memento::Memento(const State& rState) : m_State(rState) {}
State Memento::GetState() const { return m_State; }
void Memento::SetState(const State& rState) { m_State = rState; }

3. Main.cpp - 測試流程

#include "Memento.h"

int main() {
    // 1. 建立發起人,初始狀態
    Originator* pOriginator = new Originator("old state");
    pOriginator->PrintState(); // State = old state

    // 2. 備份狀態
    Memento* pMemento = pOriginator->CreateMemento();

    // 3. 修改狀態
    pOriginator->SetState("new state");
    pOriginator->PrintState(); // State = new state

    // 4. 恢復狀態
    pOriginator->SetMemento(pMemento);
    pOriginator->PrintState(); // State = old state

    delete pOriginator;
    delete pMemento;
    return 0;
}

進階應用與變體

  • 多重備忘錄: Caretaker 可用 std::stack<Memento*> 實作 Undo/Redo 功能。
  • 增量備份: 僅儲存變更差異,減少記憶體佔用(需配合命令模式)。
  • 序列化持久化: 將 Memento 序列化至磁碟/資料庫,實現跨進程狀態恢復。

適用場景

  • 需要支援「復原」操作的編輯器、IDE、遊戲存檔系統。
  • 物件狀態複雜,且必須保護封裝邊界不被外部破壞。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved