ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2022-01-21 22:01:06  阅读:145  来源: 互联网

标签:std originator include c++ state Originator 第十四章 设计模式 Memento


一、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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有