备忘录模式是一种行为型设计模式。这种模式允许我们保存对象在某些关键节点时的必要信息,以便于在适当的时候可以将之恢复到之前的状态。通常它可以用来帮助设计撤销/恢复操作。
下面是备忘录模式的类图,
图片来自https://refactoringguru.cn/design-patterns/memento,我后面实现的时候不会完全按照这个结构去实现,这里先把结构里的各个角色给大家说清楚。
【资料图】
备忘录模式中主要有这三个角色的类
上面这个类图结构是实现备忘录模式的最简单方式,真实使用的时候,Caretaker,Originator、memento 这些角色可以继续抽象出对应的接口和实现。这里就不搞那么复杂了,要举的例子比较简单,这么一拆显得这个模式用起来特别费事儿。
其实其他设计模式也是一样,学习的时候大家知道了它的结构后,在实现应用的环节不必完完全全按照结构一板一眼地全部进行实现,有的应用场景并不复杂,能合并的角色可以按需进行合并。
某线上博客平台, 需为用户提供在线编辑文章功能,文章主要包括标题 - title 和内容 - content等信息。为最大程度防止异常情况导致编辑内容的丢失, 需要提供版本暂存和Undo, Redo功能。
"版本暂存"问题可以应用备忘录模式, 将编辑器的状态完整保存起来(主要就是编辑内容),Undo和Redo的本质, 是在历史版本中前后移动把当时保存的内容加载到文章对象上。
这个例子里我们把原发器和管理人两个角色集中在Editor类型上一起实现,例子比较简单,就没有单独实现一个Article类型作为原发器角色,如果你想完全按照备忘录模式的结构实现,把Title、Content这写属性和Save方法抽离到单独的Article类型上,再让Editor嵌套组合Article即可。
下面我们根据UML类图实现一下这个带Undo、Redo功能的编辑器。
首先在IEditor 接口里定义编辑器对象要实现的行为
//编辑器接口定义typeIEditorinterface{Title(titlestring)Content(contentstring)Save()Undo()errorRedo()errorShow()}接下来定义编辑器的备忘录, 也就是编辑器的内部状态数据模型, 同时也对应一个历史版本。
"本文使用的完整可运行源码去公众号「网管叨bi叨」发送【设计模式】即可领取"typeMementostruct{titlestringcontentstringcreateTimeint64}funcnewMemento(titlestring,contentstring)*Memento{return&Memento{title,content,time.Now().Unix(),}}然后是最复杂的Editor实现,它会实现上面IEditor接口中定义的所有行为,其中的Undo、Redo方法即回退、前进方法在实现的时候就是依赖的它内部记录的一组Memento对象,通过指向不同的Memento对象来实现回退和前进功能。
"本文使用的完整可运行源码去公众号「网管叨bi叨」发送【设计模式】即可领取"//编辑器类,实现IEditor接口typeEditorstruct{titlestringcontentstringversions[]*Mementoindexint}funcNewEditor()IEditor{return&Editor{"","",make([]*Memento,0),0,}}func(editor*Editor)Title(titlestring){editor.title=title}func(editor*Editor)Content(contentstring){editor.content=content}func(editor*Editor)Save(){it:=newMemento(editor.title,editor.content)editor.versions=append(editor.versions,it)editor.index=len(editor.versions)-1}func(editor*Editor)Undo()error{returneditor.load(editor.index-1)}func(editor*Editor)load(iint)error{size:=len(editor.versions)ifsize<=0{returnerrors.New("nohistoryversions")}ifi<0||i>=size{returnerrors.New("nomorehistoryversions")}it:=editor.versions[i]editor.title=it.titleeditor.content=it.contenteditor.index=ireturnnil}func(editor*Editor)Redo()error{returneditor.load(editor.index+1)}func(editor*Editor)Show(){fmt.Printf("MockEditor.Show,title=%s,content=%s\n",editor.title,editor.content)}最后我们来测试一下Editor的版本记录功能
"本文使用的完整可运行源码去公众号「网管叨bi叨」发送【设计模式】即可领取"funcmain(){editor:=NewEditor()//testsave()editor.Title("唐诗")editor.Content("白日依山尽")editor.Save()editor.Title("唐诗登鹳雀楼")editor.Content("白日依山尽,黄河入海流.")editor.Save()editor.Title("唐诗登鹳雀楼王之涣")editor.Content("白日依山尽, 黄河入海流。欲穷千里目, 更上一层楼。")editor.Save()//testshow()fmt.Println("-------------Editor当前内容-----------")editor.Show()fmt.Println("-------------Editor回退内容-----------")for{e:=editor.Undo()ife!=nil{break}else{editor.Show()}}fmt.Println("-------------Editor前进内容-----------")for{e:=editor.Redo()ife!=nil{break}else{editor.Show()}}}运行程序后会有类似下面的显示
本文的完整源码,已经同步收录到我整理的电子教程里啦,可向我的公众号「网管叨bi叨」发送关键字【设计模式】领取。
扫码关注公众号「网管叨bi叨」
给网管个星标,第一时间吸我的知识
网管整理了一本《Go 开发参考书》收集了70多条开发实践。去公众号回复【gocookbook】领取!还有一本《k8s 入门实践》讲解了常用软件在K8s上的部署过程,公众号回复【k8s】即可领取!
觉得有用就点个在看
为满足广大投资者的理财需求,银华基金管理股份有限公司(以下简称“本公司”)决定自2023年4月19日起,银
你需要的东西酒精瓷漆喷漆器或刷子烤箱或窑炉烤瓷漆可以在表面形成一层坚韧的涂层,但如果使用不当,涂层很
ID 7是一汽大众首款纯电轿车,新车预计今年下半年上市,但是提前几个月就开始了宣传,可以看出主机厂对这款
你想了解最新最前沿的汽车资讯吗?你想了解进口汽车的最新相关报道吗?对于买车的朋友们来说了解到一手汽车
X 关闭
Go设计模式--备忘录模式,带暂存的业务功能可以参考它来实现
武穴市气象台解除大风蓝色预警【IV级/一般】-世界新消息
科技与医药赛道火热 基金投顾争相布局 世界观速讯
凉面条的做法_凉面条
枣阳市气象台发布雷电黄色预警【III级/较重】
X 关闭
上海嘉定体育馆隔离救治点首批新冠病毒感染者顺利“出院”
千里支援显真情 安徽六安捐赠的100余吨新鲜蔬菜抵沪
缉毒英雄蔡晓东烈士安葬仪式在云南西双版纳举行
多方合作推动青海建设国际生态文明高地
海口新增1例确诊病例和2例无症状感染者