from copy import deepcopy import logging, time # 备忘模式中主要有三个角色:发起人(需要进行备份的对象)、备忘录(备份的状态,即一个备份的文档)、备忘录管理者(备份文档的管理者,由他负责人与发起人的交互) # 应用场景:1、需要保存/恢复对象的状态或数据时,如游戏的存档、虚拟机的快照 # 2、需要撤销、恢复功能的场景 # 3、提供一个可回滚的操作,如数据库的事务管理 class Memento: """备忘录""" def __init__(self): self.cmdName = "" self.cmdArgs = [] def setAttributes(self, _dict): """深度拷贝字典dict中的所有属性""" self.__dict__ = deepcopy(_dict) def getAttributes(self): """获取属性字典""" return self.__dict__ def __repr__(self): return self.cmdName + " " + " ".join(self.cmdArgs) class Caretaker: """备忘录管理类""" def __init__(self): self._mementos = {} def addMemento(self, memento): name = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self._mementos[name] = memento def getMemento(self, name): return self._mementos[name] class Originator: """备份发起人""" def createMemento(self): memento = Memento() memento.setAttributes(self.__dict__) return memento def restoreFromMemento(self, memento): self.__dict__.update(memento.getAttributes()) # Doc历史指令存储 class TerminalCmd(Originator): """终端命令""" def __init__(self, text): self.cmdName = "" self.cmdArgs = [] self.parseCmd(text) def parseCmd(self, text): """从字符串中解析命令""" subStrs = self.getArgumentsFromString(text, " ") # 获取第一个字段作为命令的名称 if len(subStrs) > 0: self.cmdName = subStrs[0] if len(subStrs) > 0: self.cmdArgs = subStrs[1:] def getArgumentsFromString(self, _str, splitFlag): """通过splitFlag进行分割,获得参数数组""" if splitFlag == "": logging.warning("splitFlag为空!") return "" data = _str.split(splitFlag) result = [] for item in data: item.strip() if item != "": result.append(item) return result def showCmd(self): print(self.cmdName, self.cmdArgs) class TerminalCaretaker(Caretaker): """终端命令的备忘录管理器""" def showHistory(self): """显示历史命令""" for key, memento in self._mementos.items(): print(key + ":", memento) def testTerminal(): caretaker = TerminalCaretaker() curCmd = TerminalCmd("") while True: strCmd = input("请输入指令:") strCmd = strCmd.lower() if strCmd.startswith("q"): exit(0) elif strCmd.startswith("h"): caretaker.showHistory() elif strCmd.startswith("!"): idx = strCmd[1] curCmd.restoreFromMemento(caretaker.getMemento(idx)) curCmd.showCmd() else: curCmd = TerminalCmd(strCmd) curCmd.showCmd() caretaker.addMemento(curCmd.createMemento()) testTerminal()