【设计模式】——备忘录模式(Memento Pattern)

目录

引言

一、备忘录模式的基本概念

核心思想

备忘录模式结构

UML图

应用场景

二、备忘录模式的优点与缺点

优点

缺点

三、C++实现备忘录模式

1. 定义备忘录类

2. 定义发起人类

3. 定义管理者类

4. 客户端代码

四、总结


引言

在软件开发中,设计模式是解决常见设计问题的最佳实践。备忘录模式(Memento Pattern),又称快照模式(Snapshot Pattern),属于行为型设计模式。该模式的主要目的是在不破坏对象封装性的前提下,捕获并保存一个对象的内部状态,以便在需要时能够恢复该对象到原先的状态。本文将详细介绍备忘录模式的概念、实现步骤及其在C++中的应用。

一、备忘录模式的基本概念

核心思想

备忘录模式(Memento Pattern)的核心思想在于在不破坏封装性的前提下,捕获并保存一个对象的内部状态,以便在将来需要时能够将这些状态恢复到该对象上。这种设计模式特别适用于需要实现撤销/重做操作、事务管理或任何需要保存和恢复对象状态的场景。

备忘录模式结构

备忘录模式允许在不暴露对象内部状态的情况下捕获和恢复该状态。该模式涉及三个主要角色:

  1. 发起人(Originator):需要保存状态的对象。它负责创建备忘录对象,并记录和恢复自身的状态。
  2. 备忘录(Memento):用于存储发起人状态信息的对象。备忘录对象只能由发起人访问,防止外部对象访问发起人的状态信息。
  3. 管理者(Caretaker):负责管理备忘录对象。它通常会保存多个备忘录对象,以便于随时恢复发起人的状态。

UML图

应用场景

  1. 需要保存/恢复数据状态的场景:例如,在编辑器中实现撤销/重做功能,每次操作前后保存一个状态备忘录,需要撤销或重做时,从备忘录中恢复相应状态。

  2. 游戏保存与载入:在游戏开发中,可以利用备忘录模式保存游戏的进度,当玩家需要时,可以恢复到之前的游戏状态。

  3. 事务管理:在数据库或应用程序中管理事务时,可以利用备忘录模式在事务开始前保存当前状态,如果事务失败,则恢复到事务开始前的状态。

二、备忘录模式的优点与缺点

优点

  1. 保护封装边界:备忘录模式可以在不破坏对象封装的情况下保存关键数据,保证了数据的安全。
  2. 提供撤销功能:常用于实现命令的撤销和重做功能。
  3. 资源管理:通过备忘录管理类,可以方便地管理多个对象的状态。

缺点

  1. 内存占用:如果状态信息较为复杂或数据量较大,存储多个备忘录对象可能会占用大量内存。
  2. 增加系统的复杂性:备忘录模式涉及到多个类的交互,如果系统中大量使用此模式,可能会使代码变得复杂且难以维护。
  3. 对窄接口的影响:有时,为了保护对象的封装性,可能会设计窄接口(即限制对象的外部操作),而备忘录模式要求对象提供足够的状态信息来创建备忘录,这可能会与窄接口的设计原则产生冲突。

三、C++实现备忘录模式

1. 定义备忘录类

备忘录类用于存储发起人的状态信息。通常,它会有一个构造函数用于初始化状态,以及一个或多个方法用于获取状态信息。

// 备忘录类
class Memento {
private:
    std::string state;
public:
    Memento(const std::string& state) : state(state) {}

    std::string getState() const {
        return state;
    }
};

2. 定义发起人类

发起人类负责创建备忘录对象,并记录和恢复自身的状态。它包含保存和恢复状态的方法。


// 发起人类

class Originator {
private:
    std::string state;

public:
    void setState(const std::string& state) {
        this->state = state;
    }

    std::string getState() const {
        return state;
    }

    Memento createMemento() const {
        return Memento(state);
    }

    void restoreMemento(const Memento& memento) {
        state = memento.getState();
    }
};

3. 定义管理者类

管理者类负责保存备忘录对象,提供添加、删除和获取备忘录对象的方法。

// 管理者类
#include <iostream>
#include <vector>  
#include <memory>  

class Caretaker {
private:
    std::vector<std::shared_ptr<Memento>> mementos;

public:
    void addMemento(const std::shared_ptr<Memento>& memento) {
        mementos.push_back(memento);
    }

    std::shared_ptr<Memento> getMemento(int index) const {
        if (index < 0 || index >= mementos.size()) {
            throw std::out_of_range("Index out of range");
        }
        return mementos[index];
    }
};

4. 客户端代码

#include <iostream>  
  
int main() {  
    Originator originator;  
    Caretaker caretaker;  
  
    // 设置初始状态并保存备忘录  
    originator.setState("State 1");  
    caretaker.addMemento(std::make_shared<Memento>(originator.createMemento()));  
  
    // 修改状态并保存备忘录  
    originator.setState("State 2");  
    caretaker.addMemento(std::make_shared<Memento>(originator.createMemento()));  
  
    // 恢复到第二个备忘录的状态  
    originator.restoreMemento(*caretaker.getMemento(1));  
    std::cout << "Current state: " << originator.getState() << std::endl;  // 输出: State 2  
  
    // 恢复到第一个备忘录的状态  
    originator.restoreMemento(*caretaker.getMemento(0));  
    std::cout << "Current state: " << originator.getState() << std::endl;  // 输出: State 1  
  
    return 0;  
}

四、总结

备忘录模式是一种用于捕获和恢复对象内部状态的设计模式,它通过保存对象的内部状态信息到备忘录对象中,并允许在需要时从备忘录对象中恢复这些状态,从而达到保护对象封装性和提供撤销功能的目的。虽然备忘录模式能够解决许多与状态管理相关的问题,但它也带来了一定的复杂性和内存占用问题。因此,在使用该模式时,需要根据实际情况进行权衡和选择。

在C++中实现备忘录模式时,可以通过合理地设计备忘录类、发起人类和管理者类,并利用智能指针(如std::shared_ptr)来管理备忘录对象的生命周期,以避免内存泄漏和复杂的内存管理问题。同时,也要注意保持代码的清晰和简洁,以便于后续的维护和扩展。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

J^T

谢谢帅哥/美女

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值