zoukankan      html  css  js  c++  java
  • 设计模式---状态变化模式之备忘录模式(Memento)

    一:概念

    用于保存对象的内部状态,并在需要的时候(undo/rollback)回复对象以前的状态

    二:应用场景

    如果一个对象需要保存状态并可通过undo或rollback等操作恢复到以前的状态时,可以使用Memento模式。 

    1)一个类需要保存它的对象的状态(相当于Originator角色); 
    2)设计一个类,该类只是用来保存上述对象的状态(相当于Memento角色); 
    3)需要的时候,Caretaker角色要求Originator返回一个Memento并加以保存; 
    4)undo或rollback操作时,通过Caretacker保存的Memento恢复Originator对象的状态。

    三:动机

    在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需求,要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些公有接口来让其它对象得到对象的状态,便会暴露对象的实现细节。
    如何实现对象状态的良好保存与恢复?但同时又不会因此而破坏对象本身的封装性。

    四:模式定义

    不破坏封装性(Originator)的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原想保存的状态。
    
                                                                        ——《设计模式》GoF

    五:代码讲解

    (一)需要保存状态的对象

    class Originator
    {
        string state;
        //....多个内部状态
    public:
        Originator() {}
        Memento createMomento() {
            Memento m(state);  //在某个点时对状态(有可能需要编码序列化等操作)进行快照保存
            return m;
        }
        void setMomento(const Memento & m) {
            state = m.getState();  
        }
    };

    补充:

    函数的局部对象在当前函数被调用的时候创建,存储在栈区,在函数结束以后就会被释放,如果存在返回值,那么当前对象也会被释放,只不过在被释放前
    做了一次拷贝,拷贝到接受该返回值的另外一个对象上面,所以函数的入参和返回值其实都进行的是拷贝操作,新的对象被赋值,旧的的对象被回收

    (二)外部保存对象状态的类

    class Memento
    {
        string state;  //保存方式多样,序列化,内存流等方式
        //..和上面状态对应,存储其中有效的状态(不一定是一模一样)
    public:
        Memento(const string & s) : state(s) {}
        string getState() const { return state; }
        void setState(const string & s) { state = s; }
    };

    (三)使用

    int main()
    {
        Originator orginator;  //原发器
        
        //捕获对象状态,存储到备忘录
        Memento mem = orginator.createMomento();
        
        //... 改变orginator状态
        
        //从备忘录中恢复
        orginator.setMomento(memento);
    
    }

    六:类图(结构)

    七:要点总结

    (一)备忘录(Memento)存储原发器(Originator)对象的内部状态,在需要时恢复原发器的状态。

    (二)Memento模式的核心是信息隐藏,即Originator需要向外接隐藏信息,保持其封装性。但同时又需要将其状态保持到外界(Memento)

    (三)由于现代语言运行时(如C#、java等)都具有相当的对象序列化支持,因此往往采用效率较高、又较容易正确实现的序列化方案来实现Memento模式。

    八:案例演示

    (一)备忘录实现

    //备忘录
    class MememTo
    {
    private:
        string m_name;
        int m_age;
    public:
        MememTo(string name,int age)  //构造数据来源于我们想要保存的信息
        {
            this->m_name = name;
            this->m_age = age;
        }
    
        void setName(string name)
        {
            this->m_name = name;
        }
    
        void setAge(int age)
        {
            this->m_age = age;
        }
    
        string getName()
        {
            return m_name;
        }
    
        int getAge()
        {
            return m_age;
        }
    };

    (二)构造原发器

    //原发器
    class Person
    {
    private:
        string m_name;
        int m_age;
    public:
        Person(string name,int age)
        {
            this->m_age = age;
            this->m_name = name;
        }
    
        void setName(string name)
        {
            this->m_name = name;
        }
    
        void setAge(int age)
        {
            this->m_age = age;
        }
    
        string getName()
        {
            return m_name;
        }
    
        int getAge()
        {
            return m_age;
        }
    
        void printInfo()
        {
            cout << m_name << " is " << m_age << endl;
        }
    public:
        //创建备份
        MememTo* createMememTo()
        {
            return new MememTo(m_name, m_age);
        }
        
        //恢复备份
        void SetMememTo(MememTo* memto)
        {
            m_age = memto->getAge();
            m_name = memto->getName();
        }
    };

    (三)实现管理者

    //管理者,写在外面调用有点多余,直接将main作为管理者
    class CareTaker
    {
    private:
        MememTo* m_memto;
    public:
        CareTaker(MememTo* mem)
        {
            this->m_memto = mem;
        }
    
        MememTo* getMememTo()
        {
            return m_memto;
        }
    
        void setMememTo(MememTo* mem)
        {
            this->m_memto = mem;
        }
    };
    void main()
    {
        Person* p = new Person("zhangsan", 18);
        p->printInfo();
        //创建备份
        MememTo* membak = p->createMememTo();
        p->createMememTo();
    
        p->setAge(35);
        p->setName("lisi");
        p->printInfo();
    
        //恢复信息
        p->SetMememTo(membak);
        p->printInfo();
    
        system("pause");
        return;
    }

  • 相关阅读:
    记周日一次故障意外
    每周一坑-【3月第1周】
    关于计划任务的一个小需求-优化篇
    400篇博客的一个里程碑
    关于计划任务的一个小需求-实现篇
    关于计划任务的一个小需求
    微服务优雅停机研究
    NSUInteger设为负数
    Mac上运行第一个Flutter项目
    Vue filtersfilter、computed、methods、watch对比
  • 原文地址:https://www.cnblogs.com/ssyfj/p/9545969.html
Copyright © 2011-2022 走看看