编程语言
首页 > 编程语言> > 设计模式-第十四章-备忘录模式(c++)

设计模式-第十四章-备忘录模式(c++)

作者:互联网

一、UML图

二、包含的角色

Memento类, 是原发器状态快照的值对象 (value object)。 通常做法是将备忘录设为不可变的, 并通过构造函数一次性传递数据。

Originator类可以生成自身状态的快照, 也可以在需要时通过快照恢复自身状态。

Caretaker类, 仅知道 “何时” 和 “为何” 捕捉原发器的状态, 以及何时恢复状态。通过保存备忘录栈来记录原发器的历史状态。 当原发器需要回溯历史状态时, 负责人将从栈中获取最顶部的备忘录, 并将其传递给原发器的恢复 (restoration) 方法。

三、特点

备忘录模式是一种行为设计模式, 允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。

允许你复制对象中的全部状态 (包括私有成员变量), 并将其独立于对象进行保存。 尽管大部分人因为 “撤销” 这个用例才记得该模式, 但其实它在处理事务 (比如需要在出现错误时回滚一个操作) 的过程中也必不可少。让对象自行负责创建其状态的快照。 任何其他对象都不能读取快照, 这有效地保障了数据的安全性。

四、代码实现

Memento类

#pragma once
#include <chrono>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <string>

/**
 * The Memento interface provides a way to retrieve the memento's metadata, such
 * as creation date or name. However, it doesn't expose the Originator's state.
 */
class Memento
{
public:
    Memento(std::string state) : state_(state)
    {
        this->date_ = time_in_HH_MM_SS_MMM();
    }
    virtual ~Memento() {}

public:
    std::string state() const
    {
        return this->state_;
    }

    std::string date() const
    {
        return this->date_;
    }

protected:
 
    std::string time_in_HH_MM_SS_MMM()
    {
        using namespace std::chrono;

        // get current time
        auto now = system_clock::now();

        // get number of milliseconds for the current second
        // (remainder after division into seconds)
        auto ms = duration_cast<milliseconds>(now.time_since_epoch()) % 1000;

        // convert to std::time_t in order to convert to std::tm (broken time)
        auto timer = system_clock::to_time_t(now);

        // convert to broken time
        std::tm bt = *std::localtime(&timer);

        std::ostringstream oss;
        oss << std::put_time(&bt, "%H:%M:%S"); // HH:MM:SS
        oss << '.' << std::setfill('0') << std::setw(5) << ms.count();

        return oss.str();
    }
    std::string state_;
    std::string date_;
};

Originator类

#pragma once
#include "Memento.h"

#include <iostream>
#include <random>

class Originator
{
    /**
     * @var string For the sake of simplicity, the originator's state is stored
     * inside a single variable.
     */
private:
    std::string state_;
    int index_;
public:
    Originator(std::string state) : state_(state)
    {
        index_=1;
        std::cout << "Originator: My initial state is: " << this->state_ << "\n";
    }

    /**
     * Saves the current state inside a memento.
     */
    Memento *Save()
    {
        return new Memento(this->state_);
    }
    /**
     * Restores the Originator's state from a memento object.
     */
    void Restore(Memento *memento)
    {
        this->state_ = memento->state();
        std::cout << "Originator Restore: My state has changed to: " << this->state_ << " : "<< memento->date() << "\n";
    }


    void ChangeState()
    {
        this->state_ = std::string("状态"+ std::to_string(index_++));
        std::cout << "Originator ChangeState: My state has changed to: " << this->state_ <<  "\n";
    }
};

Caretaker类

#pragma once

#include "Originator.h"
#include <iostream>
#include <random>
/**
 * The Caretaker doesn't depend on the Concrete Memento class. Therefore, it
 * doesn't have access to the originator's state, stored inside the memento. It
 * works with all mementos via the base Memento interface.
 */
class Caretaker
{

public:
    Caretaker(Originator *originator) : originator_(originator)
    {
        this->originator_ = originator;
    }
    ~Caretaker()
    {
        for (auto it = mementos_.begin(); it != mementos_.end(); ++it)
        {
            if ((*it) != nullptr)
            {
                delete (*it);
            }
        }
    }

    void Backup()
    {
        std::cout << "\nCaretaker: Saving Originator's state...\n";
        this->mementos_.push_back(this->originator_->Save());
    }
    void Undo()
    {
        if (!this->mementos_.size())
        {
            return;
        }
        Memento *memento = this->mementos_.back();
        this->mementos_.pop_back();
        std::cout << "Caretaker: Restoring state to: " << memento->date() << "\n";
        try
        {
            this->originator_->Restore(memento);
        }
        catch (...)
        {
            this->Undo();
        }
    }
    void ShowHistory() const
    {
        std::cout << "Caretaker: Here's the list of mementos:\n";
        for (Memento *memento : this->mementos_)
        {
            std::cout << memento->state() << " : "<<memento->date() << "\n";
        }
    }

private:
    std::vector<Memento *> mementos_;
    Originator *originator_;
};

main

#include "Caretaker.h"
#include "Originator.h"
#include <unistd.h>

int main()
{
    Originator *originator = new Originator("状态0");
    Caretaker *caretaker = new Caretaker(originator);
    caretaker->Backup(); // 保存状态

    sleep(1);
    originator->ChangeState();
    caretaker->Backup(); // 保存状态
    
    sleep(1);
    originator->ChangeState();
    caretaker->Backup(); // 保存状态

    caretaker->ShowHistory();
    printf("\nClient: Now, let's rollback!\n\n");
    caretaker->Undo();
    printf("\nClient: Once more!\n\n");
    caretaker->Undo();
    printf("\nClient: Once more!\n\n");
    caretaker->Undo();
    return 0;
}

标签:std,originator,include,c++,state,Originator,第十四章,设计模式,Memento
来源: https://blog.csdn.net/fanrongwoaini/article/details/83004778