• 【设计模式】备忘录


    备忘录,其实名字也比较形象。

    我们经常遇到将一个类的状态恢复到历史版本的需求。比如一个记事本,想保存一个上N个状态,通过Ctrl+Z可以恢复此前编辑内容。备忘录就非常适合这种场景。此时发起者类,希望能够将自身状态保留在某处,而且不希望过多的暴露细节。为了上述目的,发起者会在某个时刻通过new出一个备忘类对象,并将该对象托管给管理者类。然后需要恢复状态时,又从管理者类中获取具体状态,将自身恢复到某个状态。

    为了保持封装性,备忘录一般除了将自己暴露给发起者外(或者可以认为是发起者将自己状态暴露给了备忘类),不为外部类提供任何访问状态相关接口。C++中这个通常是通过将自己所有接口都改成private(包括构造函数),然后将发起者设为自己的友元类来实现。

    写了个demo,可以支持多个版本:

    /***************************************************************************
     * 
     * Copyright (c) 2013 itegel.com, Inc. All Rights Reserved
     * 
     **************************************************************************/
     
     
     
    /**
     * @file test_memento.cpp
     * @author itegel
     * @date 2013/06/08 11:29:08
     * @brief 
     *  
     **/
    
    #include <string>
    #include <map>
    #include <iostream>
    using namespace std;
    
    class State{
        public:
            int version;
            string content;
    };
    
    class Memento{
        public:
        private:
            friend class NoteBook;
            Memento(State state) : _state(state){}
            ~Memento(){}
    
            State * GetState(){
                return &_state;
            }
            void SetState(State state){
                _state = state;
            }
            State _state;
    };
    
    //originator
    class NoteBook{
        public:
            NoteBook(int version, string content){
                _state.version = version;
                _state.content = content;            
            }
            
            NoteBook(State & state):_state(state){
                        
            }
            
            void SetMemento(Memento * mem){
                _state = mem->_state;
            }
    
            Memento * GetMemento(){
                return new Memento(_state);
            }
    
            void SetState(int version, string content){
                _state.version = version;
                _state.content = content;
            }
            
            int GetVersion(){
                return _state.version;
            }
    
            void PrintState(){
                cout<<"Note:\n\tversion:\t"<<_state.version<<endl<<"\tcontent:\t"<<_state.content<<endl;
            }
    
        private:
            State _state;
    };
    
    
    class CareTaker{
        public:
            CareTaker(){}
            void Save(int id, Memento * mem){
                _memento_map[id] = mem;
            }
            Memento * GetMemento(int id){
                return _memento_map[id];
            }
        private:
            map<int, Memento *> _memento_map;
    };
    
    int main(){
        NoteBook my_note(0, "");
        CareTaker care_taker;
    
        my_note.PrintState();
        cout<<"Save State 0!"<<endl;
        care_taker.Save(my_note.GetVersion(), my_note.GetMemento());
    
        cout<<endl<<"Edit for 1st time!"<<endl;
        my_note.SetState(1, "Hello world!");
        my_note.PrintState();
        care_taker.Save(my_note.GetVersion(), my_note.GetMemento());
        
        cout<<endl<<"Edit for 2nd time!"<<endl;
        my_note.SetState(2, "Hello World! It is the 2nd version!");
        my_note.PrintState();
        care_taker.Save(my_note.GetVersion(), my_note.GetMemento());
        
        cout<<endl<<"Edit for 3rd time!"<<endl;
        my_note.SetState(3, "Hello Itegel! It is the 3rd version!");
        my_note.PrintState();
        care_taker.Save(my_note.GetVersion(), my_note.GetMemento());
    
    
        cout<<endl<<"Restore 2nd version:"<<endl;
        Memento * mem = care_taker.GetMemento(2);
        my_note.SetMemento(mem);
        my_note.PrintState();
        
        cout<<endl<<"Restore 0 version:"<<endl;
        mem = care_taker.GetMemento(0);
        my_note.SetMemento(mem);
        my_note.PrintState();
    
        return 0;
    }
    
    


    执行结果:

    Note:
    	version:	0
    	content:	
    Save State 0!
    
    Edit for 1st time!
    Note:
    	version:	1
    	content:	Hello world!
    
    Edit for 2nd time!
    Note:
    	version:	2
    	content:	Hello World! It is the 2nd version!
    
    Edit for 3rd time!
    Note:
    	version:	3
    	content:	Hello Itegel! It is the 3rd version!
    
    Restore 2nd version:
    Note:
    	version:	2
    	content:	Hello World! It is the 2nd version!
    
    Restore 0 version:
    Note:
    	version:	0
    	content:	


    备忘录模式使用场景应该比较固定,但是其实现可以很灵活。主要思想就是将自己的状态托管给一个其他类,但是又不想过多的暴露自身信息,从而引入了备忘录类。变化的地方应该是状态成员的变化吧。此时只需要修改State类就好,其他其实可以做到不用修改(除了发起者关于这个新增状态信息的维护)。


    P.S. 到这儿23个设计模式中行为模式都写过一些demo了。好久没抽空写东西了,发现其实写代码都有些生疏了。

    这些天一直抽空写一些demo,理解还不够深,但是代码都是自己一行一行敲进去的。这样体会会深一些吧。其实很多时候,还是需要跟实际项目结合,理解会更深一些。个人体会是,程序员多写代码才是王道。

  • 相关阅读:
    Calendar日历类
    DateFormat类和SimpleDateFormat类
    Date时间类(java.util.Date)
    时间处理相关类
    不可变和可变字符序列使用陷阱
    String类
    搬圆桌问题
    重温经典之排序 java实现
    i++ 和 ++i
    Intellij Idea 使用技巧 updating
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3127472.html
Copyright © 2020-2023  润新知