概念解析
备忘模式,指的是在不破坏内部结构的前提下捕获一个对象的内部状态,这样便可将该对象恢复到原先的保持状态。备忘模式的最大功能是备份,其主要的三个角色:
- 发起人(Originator):需要进行备份的对象
 - 备忘录(Mementor):备份的状态,即一个备份的存档
 - 备忘管理者(Caretaker):备份存档的管理者,由它负责与发起人的交互
 
备忘模式类图如下:

备忘模式的优点:
- 能够恢复之前的状态
 - 实现了信息的封装,用户不需要关心状态的保存细节
 
常用场景:
- 存档/快照场景
 - 撤销/恢复功能
 - 回滚操作
 
设计模板
备忘模式的代码框架如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from copy import deepcopy
class Memento():
    """备忘录"""
    def set_attributes(self, dict):
        """深度拷贝字典dict中的所有属性"""
        self.__dict__ = deepcopy(dict)
    def get_attributes(self):
        """获取属性字典"""
        return self.__dict__
class Caretaker():
    """备忘录管理类"""
    def __init__(self):
        self._mementors = {}
    def add_memento(self, name, memento):
        # 不同name不同备忘录
        self._mementors[name] = memento
    def get_memento(self, name):
        return self._mementors[name]
class Originator():
    """备份发起人"""
    def create_memento(self):
        memento = Memento()
        memento.set_attributes(self.__dict__)
        return memento
    def restore_from_memento(self, memento):
        self.__dict__.update(memento.get_attributes())
实例分析
场景说明:模拟DOS命令/Linux终端命令下查看历史命令:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 模板中的关键类
from pattern.Memento import Originator, Caretaker, Memento
import logging
class TerminalCmd(Originator):
    """终端命令"""
    def __init__(self, text):
        self.__cmd_name = ""
        self.__cmd_args = []
        self.parse_cmd(text)
    def parse_cmd(self, text):
        """从字符串中解析命令"""
        pass
    def get_arguments_from_string(self, str, split_flag):
        """通过split_flag进行分割,获取参数数组"""
        pass
    def show_cmd(self):
        print(self.__cmd_name, self.__cmd_args)
class TerminalCaretaker(Caretaker):
    """终端命令的备忘录管理类"""
    def show_history_cmds(self):
        """显示历史命令"""
        for key, obj in self._mementors.items():
            name = ""
            value = []
            if obj._TerminalCmd.__cmd_name:
                name = obj._TerminalCmd.__cmd_name
            if obj._TerminalCmd.__cmd_args:
                value = obj._TerminalCmd.__cmd_args
            print("第%s条命令:%s %s" % (key, name, value))
def test_terminal():
    cmd_idx = 0
    caretaker = TerminalCaretaker()
    cur_cmd = TerminalCmd("")
    while True:
        str_cmd = input("请输入指令:")
        str_cmd = str_cmd.lower()
        if str_cmd.startswith("q"):
            exit(0)
        elif str_cmd.startswith("h"):
            caretaker.show_history_cmds()
        # 通过"!"符号表示获取历史的某个指令
        elif str_cmd.startswith("!"):
            idx = int(str_cmd[1:])
            cur_cmd.restore_from_memento(caretaker.get_memento(idx))
            cur_cmd.show_cmd()
        else:
            cur_cmd = TerminalCmd(str_cmd)
            cur_cmd.show_cmd()
            caretaker.add_memento(cmd_idx, cur_cmd.create_memento())
        cmdIdx += 1