设计模式 备忘录模式

1、memento.h

#ifndef MEMENTO_H
#define MEMENTO_H

#include <iostream>
#include <vector>
using namespace std;

class Memento;
class Employee //原发器(Originator),创建一个备忘录. 用以记录当前时刻它的内部状态.使用备忘录恢复内部状态.
{
public:
    Employee();
    virtual ~Employee();
    void SetId(int);
    int GetId();
    char* GetName();
    void SetName(char*);
    void SetSalary(double);
    double GetSalary();
    void SetMemento(Memento*);
    Memento* GetMemento();
    friend std::ostream& operator<<(std::ostream& os, Employee& employee);
private:
    int m_nId;
    char* m_pName;
    double m_dSalary;
};

class Memento //Memento(备忘录),存储原发器对象的内部状态,防止原发器以外的对象访问备忘录.
{
public:
    Memento(int, char*, double);
    virtual ~Memento();
    friend class Employee;//声明为友元类,可以访问这个类的成员变量,就是说,在Employee成员函数中有Memento对象,
                          //则,可以引用Memento对象的私有变量,如m_nId
private:
    int m_nId;
    char* m_pName;
    double m_dSalary;
};

class Caretaker //看管者(caretaker),负责保存好备忘录,不能对备忘录的内容操作或检查.
{
public:
    Caretaker(Employee*);
    virtual ~Caretaker();
    void SaveEmployee();
    void UnsaveEmployee();
private:
    std::vector<Memento*> m_vMementos;
    Employee* m_pEmployee;
};

#endif // MEMENTO_H

2、memento.cpp

#include "memento.h"


Employee::Employee(){}

Employee::~Employee(){}

void Employee::SetId(int nId)
{
    m_nId = nId;
}

int Employee::GetId()
{
    return m_nId;
}

void Employee::SetName(char* pName)
{
    m_pName = pName;
}

char* Employee::GetName()
{
    return m_pName;
}

void Employee::SetSalary(double dSalary)
{
    m_dSalary = dSalary;
}

double Employee::GetSalary()
{
    return m_dSalary;
}

void Employee::SetMemento(Memento* pMemento)
{
    m_nId = pMemento->m_nId;
    m_pName = pMemento->m_pName;
    m_dSalary = pMemento->m_dSalary;
}

Memento* Employee::GetMemento()
{
    return new Memento(m_nId, m_pName, m_dSalary);
}

std::ostream& operator<<(std::ostream& os, Employee& employee)
{
    return os << "ID:" << employee.m_nId << ", "
            << "Name:" << employee.m_pName << ", "
            << "Salary:" << employee.m_dSalary << endl;
}

Memento::Memento(int nId, char* pName, double dSalary)
{
    m_nId = nId;
    m_pName = pName;
    m_dSalary = dSalary;
}

Memento::~Memento(){}

Caretaker::Caretaker(Employee* pEmployee)
{
    m_pEmployee = pEmployee;
}

Caretaker::~Caretaker()
{
    if(m_pEmployee != NULL)
    {
        delete m_pEmployee;
        m_pEmployee = NULL;
    }
}

void Caretaker::SaveEmployee()
{
    Memento* pMemento = m_pEmployee->GetMemento();
    m_vMementos.push_back(pMemento);
}

void Caretaker::UnsaveEmployee()
{
    if(m_vMementos.size() > 0)
    {
        Memento* pMemento = m_vMementos.at(m_vMementos.size() - 1);
        m_vMementos.pop_back();
        m_pEmployee->SetMemento(pMemento);
    }
}

3、main.cpp
/*
作者:jhluroom弹   QQ:454676244  MSN:jhlu0815@hotmail.com
开发IDE:qt creater
开发环境:QT C++
参考网站:神秘果:http://www.shenmiguo.com/

定义:
在不破坏封装性的前提下.捕获一个对象的内部状态. 并在该对象之外保存这个状态.这样以后就可以将该对象恢复到以前保存的状态.


理解:
1.备忘录(Memento)角色:备忘录角色存储“备忘发起角色”的内部状态。“备忘发起角色”根据需要决定备忘录角色存储“备忘发起角色”
  的哪些内部状态。为了防止“备忘发起角色”以外的其他对象访问备忘录。备忘录实际上有两个接口,“备忘录管理者角色”只能看到备忘录
  提供的窄接口——对于备忘录角色中存放的属性是不可见的。“备忘发起角色”则能够看到一个宽接口——能够得到自己放入备忘录角色中属性。
2.备忘发起(Originator)角色:“备忘发起角色”创建一个备忘录,用以记录当前时刻它的内部状态。在需要时使用备忘录恢复内部状态。
3.备忘录管理者(Caretaker)角色:负责保存好备忘录。不能对备忘录的内容进行操作或检查。

要点:
1.备忘录模式(Memento)的定义为:在不破坏封闭的前提下,捕获并保存一个对象的内部状态,这样可以将对象恢复到原先的状态。
2.很多应用程序中的Ctrl+Z会取消最后一次用户操作,如果不用备忘模式,看管者(caretaker)对象要备份原发器(Originator)
  对象状态,并且要清楚原发器内部的结构,这样在原发器上的任何修改,看管者都要做相应的修改,使用备记录模式可以解决这种问题,
  备忘录封闭保存备份的状态,当原发器提出备份请求,它就会创建一个备忘录对象返回给看者。
3.Memento模式中封装的是需要保存的状态,当需要恢复的时候才取出来进行恢复。原理很简单,实现的时候需要注意一个地方:
  窄接口和宽接口。
  宽接口,就是一般意义上的接口,把对外的接口作为public成员;
  窄接口,把接口作为private成员,而把需要访问这些接口函数的类作为这个类的友元类,也就是说接口只暴露给了对这些接口感兴趣的类,
  而不是暴露在外部。

应用:
1.需要保存一个对象在某时刻的状态.以备以后恢复.
2.保存状态时不想让其它对象直接得到对象内部的实现细节。
3.假设有一雇员信息,我们可对其进行修改,当多次修改后,想撤消回原来的状态,这时可以用备忘录模式对雇员信息进行备份,
  需要还原时就可对其进行撤消操作。如下面程序所示:

以上文字说明,从网上整理而来,有可能部分与其他同仁相同,请谅解,希望我们能够共同交流,谢谢!
*/

#include <QtCore/QCoreApplication>

#include "memento.h"

int main(int argc, char *argv[])
{
    cout << "=== jhluroom start ========" << endl;

    Employee* pEmployee = new Employee();
    Caretaker* pCaretaker = new Caretaker(pEmployee);

    pEmployee->SetId(1);
    pEmployee->SetName("xiao li");
    pEmployee->SetSalary(6000.00);
    pCaretaker->SaveEmployee();
    cout <<"撤消前: "<< *pEmployee;

    pEmployee->SetId(2);
    pEmployee->SetName("xiao wang");
    pEmployee->SetSalary(8000.00);
    pCaretaker->SaveEmployee();
    cout <<"撤消前: "<< *pEmployee;

    pEmployee->SetId(3);
    pEmployee->SetName("xiao lu");
    pEmployee->SetSalary(15000.00);
    pCaretaker->SaveEmployee();
    cout <<"撤消前: "<< *pEmployee;

    pCaretaker->UnsaveEmployee();
    cout << "撤消后: " << *pEmployee;
    pCaretaker->UnsaveEmployee();
    cout << "撤消后: " << *pEmployee;
    pCaretaker->UnsaveEmployee();
    cout << "撤消后: " << *pEmployee;

    cout << "=== jhluroom finish _^_ ===" << endl;
    return 0;
}

运行结果:

=== jhluroom start ========

撤消前: ID:1, Name:xiao li, Salary:6000
撤消前: ID:2, Name:xiao wang, Salary:8000
撤消前: ID:3, Name:xiao lu, Salary:15000
撤消后: ID:3, Name:xiao lu, Salary:15000
撤消后: ID:2, Name:xiao wang, Salary:8000
撤消后: ID:1, Name:xiao li, Salary:6000

=== jhluroom finish _^_ ===


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值