一天一种设计模式之二-----备忘录模式
2019独角兽企业重金招聘Python工程师标准>>>
一.备忘录模式
备忘录模式属于三种设计模式中的行为型模式(另外两种是创建型模式和结构型模式)。
定义:在不破坏封闭性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将改变了的对象恢复到原先保存的状态。
之所以需要存储改变前的对象,是因为java对象的传递是引用传递。A a1=a,a里面的东西变就等同于a1里面的东西变。
备忘录模式的结构:
发起人:负责记录当前时刻的内部状态,负责定义那些属于备忘范围的状态,负责创建和恢复备忘录数据。
备忘录:负责存储发起人对象的内部状态,在需要的时候提供发起人需要的内部状态。
管理角色:对备忘录进行管理,保存和提供备忘录。
优点:
当发起人角色中的状态改变时,有可能这是个错误的改变,我们使用备忘录模式就可以还原。
备份的状态是保存在发起人角色之外的,这样,发起人角色就不需要对哥哥备份状态进行管理。
如果有需要提供回滚操作的需求,使用备忘录模式非常合适
缺点:
在实际应用中,备忘录模式多事多状态和多备份的,发起人角色的状态需要存储到备忘录对象中,对字段的小号是比较严重的。
从设计模式角度讲:个人感觉他对六大设计模式原则的体现不是很大,只能说满足单一职责原则把,比如一个类的实例如果想要从不能备忘改为需要备忘,通过该模式,我们还是要为该类增加一个保存和恢复的方法,违背了开闭原则,client端调用的时候需要知道。为什么不直接定义一个容器,拷贝一个该对象,需要回复的时候再赋值过去呢(这样貌似又不伦不类了,因为体现不出来备忘是某个对象的能力,略纠结啊)。(欢迎大神透彻分析下)
二.测试代码
简单版测试用例:
public class BeiwangluTest {public static void main(String[] args) {Originator originator=new Originator();originator.setState("状态1");Caretaker caretaker=new Caretaker();caretaker.setMemento(originator.createMemento());originator.setState("状态2");originator.restorMemento(caretaker.getMemento());System.out.println(originator.getState());;//这是之前的状态originator.createMemento();//这是之前的memento}
}
/*** 发起ren * @author 58**/
class Originator{private String state="";public String getState() {return state;}public void setState(String state) {this.state = state;}public Memento createMemento(){return new Memento(this.state);}public void restorMemento(Memento memento){this.setState(memento.getState());}}
/*** 备忘录* @author 58**/
class Memento{private String state;public Memento(String state){this.state = state;}public String getState() {return state;}public void setState(String state) {this.state = state;}
}/*** 管理角色* @author 58**/
class Caretaker{private Memento memento;public Memento getMemento() {return memento;}public void setMemento(Memento memento) {this.memento = memento;}}
上述代码只做到恢复了一个状态,一般情况下我们需要恢复的是一个复杂的对象。
最常用的方法是在memento中增加一个map容器来存储所有的状态,在caretaker类中同样适用一个map容器存储所有备份。下面代码如下(应该也可以通过深拷贝实现,通过beanutils来实现会更更简单,有时间的话试试)
(话外代码规范:写代码时名字要起好,在方法中list list=xxx这种就不好,应该表示清楚list是干嘛的,不然看起来很费劲。简单命名应该只出现在循环遍历中,trycatch等代码经常会给我们生成一个//TODO注释,这个注释不要留,会让有代码洁癖的人反感,可以从eclipese设置里去掉,要是不知道为什么,自己去百度//TODO,//XXX,//FIXME 这些注释各自都是干嘛用的,严格要求从我做起)
public class BeiwangluTest {public static void main(String[] args) {Originator ori=new Originator();Caretaker caretaker=new Caretaker();ori.setState1("中国");ori.setState2("强盛");ori.setState3("繁荣");System.out.println("状态1"+ori);caretaker.setMemento("001",ori.createMemento());ori.setState1("软件");ori.setState2("架构");ori.setState3("优秀");System.out.println("状态2"+ori);ori.restorMemento(caretaker.getMemento("001"));System.out.println("回复后的状态"+ori);}
}/*** 发起人* * @author 58**/
class Originator {private String state1 = "";private String state2 = "";private String state3 = "";public Memento createMemento() {return new Memento(BeanUtils.backupProp(this));}public void restorMemento(Memento memento) {BeanUtils.restoreProp(this, memento.getStateMap());}public String getState1() {return state1;}public void setState1(String state1) {this.state1 = state1;}public String getState2() {return state2;}public void setState2(String state2) {this.state2 = state2;}public String getState3() {return state3;}public void setState3(String state3) {this.state3 = state3;}@Overridepublic String toString() {return "Originator [state1=" + state1 + ", state2=" + state2+ ", state3=" + state3 + "]";}}/*** 备忘录* * @author 58**/
class Memento {private Map<String, Object> stateMap;public Memento(Map<String, Object> map) {this.stateMap = map;}public Map<String, Object> getStateMap() {return stateMap;}public void setStateMap(Map<String, Object> stateMap) {this.stateMap = stateMap;}}/*** 管理角色* * @author 58**/
class Caretaker {private Map<String, Memento> meMap = new HashMap<String, Memento>();public Memento getMemento(String index) {return meMap.get(index);}public void setMemento(String index, Memento memento) {this.meMap.put(index, memento);}private Memento memento;public Memento getMemento() {return memento;}public void setMemento(Memento memento) {this.memento = memento;}}class BeanUtils {public static Map<String, Object> backupProp(Object bean) {Map<String, Object> result = new HashMap<String, Object>();try {BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();for (PropertyDescriptor descriptor : descriptors) {String fieldName = descriptor.getName();Method getter = descriptor.getReadMethod();// TODO null和new Object[]{}是不一样的,null一般是执行抽象方法。Object fieldValue = getter.invoke(bean, new Object[]{});if (!fieldName.equalsIgnoreCase("class")) {result.put(fieldName, fieldValue);}}} catch (IntrospectionException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}return result;}public static void restoreProp(Object bean, Map<String, Object> propMap) {try {BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();for (PropertyDescriptor descriptor : descriptors) {String fieldName = descriptor.getName();if (propMap.containsKey(fieldName)) {Method setterMethod = descriptor.getWriteMethod();setterMethod.invoke(bean,new Object[] { propMap.get(fieldName) });}}} catch (IntrospectionException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}
}
转载于:https://my.oschina.net/u/2323537/blog/631874
一天一种设计模式之二-----备忘录模式相关推荐
- 一天一种设计模式之六-----工厂方法模式
2019独角兽企业重金招聘Python工程师标准>>> 一.工厂方法模式 工厂方法模式属于创建型模式. 工厂方法模式定义:定义一个用于创建对象的借口,让子类决定实例化哪一个类.工厂方 ...
- 备战面试日记(3.3) - (设计模式.23种设计模式之结构型模式)
本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试. 记录日期:2022.1.9 大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习. 文章 ...
- 备战面试日记(3.2) - (设计模式.23种设计模式之创建型模式)
本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试. 记录日期:2022.1.6 大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习. 文章 ...
- 备战面试日记(3.4) - (设计模式.23种设计模式之行为型模式)
本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试. 记录日期:2022.1.12 大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习. 文 ...
- 走穿java23种设计模式-15责任链模式详解
走穿java23种设计模式-15责任链模式详解 责任链模式是一种常见的行为模式. 一.责任链模式的现实场景 习伟过生日邀请了很多朋友到KTV一起庆祝,为了增加欢乐的气氛,习伟建议大家一起玩击鼓传花的游 ...
- JAVA23种设计模式(2)-结构型模式7种
JAVA23种设计模式(2)-结构型模式7种 把类结合在一起形成更大的结构 适配器模式(adapter) 一句话:将一个类的接口转换成另一种接口.让原本接口不兼容的类可以兼容 这是平时比较常见的一种模 ...
- 走穿java23种设计模式--18中介者模式详解
走穿java23种设计模式–18中介者模式详解 中介者模式也称调停者模式,是一种比较简单的模式. 一.中介者模式的现实场景 蔡良因为上次表白时对方只看重他的物质方面,所以他对女朋友这个问题有点失望.因 ...
- 从王者荣耀看设计模式(二十二.备忘录模式)
从王者荣耀看设计模式 一.简介 点击王者荣耀商店法术的装备栏,存在有"贤者的庇护"这一装备.在对战中,当玩家处于死亡状态时,会触发此装备的效果,能够让英雄重新复活. ┬┴┬┌─ ● ...
- 一天一种设计模式之五-----代理模式
2019独角兽企业重金招聘Python工程师标准>>> 一.代理模式简介 代理模式属于结构型模式 定义:代理模式为其他对象提供一种代理以控制对这个对象的访问. 代理模式是java框架 ...
最新文章
- 订书机是怎样发明的?
- 开源内容管理系统 php mysql_「分享」7 个精致的 PHP 开源内容管理系统(CMS)
- Codeforces 991E. Bus Number (DFS+排列组合)
- RFID位置数据这么多,企业应该怎么利用?
- 详细解读神经网络十大误解,再也不会弄错它的事情原理
- qt 无法打开shell32_在Qt中用默认程序打开文件
- connect by prior id= pid start with id='1' 树结构查询
- KORG Opsix Native Mac - 音频数字合成器
- 谷歌浏览器的一个新特点—关于获取iframe的parent对象
- python如何截长图_python+selenium实现长截图
- lambda函数 python菜鸟教程-Python - lambda函数
- 毫无PS痕迹 你的第一本Photoshop书pdf
- 电脑如何设置u盘启动,u盘启动项设置方法
- Android 项目集成有米 SDK 添加广告
- 剑指 Offer 12-20
- 使用potplayer播放器看直播
- c语言结构体编辑学生成绩管理,C语言基于结构体的学生信息管理系统实现
- Eboot之函数BootloaderMain函数分析
- Python数据可视化 Pyecharts 制作 Tab 选项卡多图控制
- 我是一个假的acmer