关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 算法设计 »23种设计模式之备忘录模式

    23种设计模式之备忘录模式

    2015-04-06 00:00:00 出处:卡奴达摩的专栏
    分享

    定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态

    类型:行为类

    类图:

    23种设计模式(15):备忘录模式

    我们在编程的时候,经常需要保存对象的中间状态,当需要的时候,可以恢复到这个状态。比如,我们使用Eclipse进行编程时,如果编写失误(例如不小心误删除了几行代码),我们希望返回删除前的状态,便可以使用Ctrl+Z来进行返回。这时我们便可以使用备忘录模式来实现。

    备忘录模式的结构

    发起人:记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录数据。 备忘录:负责存储发起人对象的内部状态,在需要的时候提供发起人需要的内部状态。 管理角色:对备忘录进行管理,保存和提供备忘录。

    通用代码实现

    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 restoreMemento(Memento memento){
    		this.setState(memento.getState());
    	}
    }
    
    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;
    	}
    }
    class Caretaker {
    	private Memento memento;
    	public Memento getMemento(){
    		return memento;
    	}
    	public void setMemento(Memento memento){
    		this.memento = memento;
    	}
    }
    public class Client {
    	public static void main(String[] args){
    		Originator originator = new Originator();
    		originator.setState("状态1");
    		System.out.println("初始状态:"+originator.getState());
    		Caretaker caretaker = new Caretaker();
    		caretaker.setMemento(originator.createMemento());
    		originator.setState("状态2");
    		System.out.println("改变后状态:"+originator.getState());
    		originator.restoreMemento(caretaker.getMemento());
    		System.out.println("恢复后状态:"+originator.getState());
    	}
    }

    代码演示了一个单状态单备份的例子,逻辑非常简单:Originator类中的state变量需要备份,以便在需要的时候恢复;Memento类中,也有一个state变量,用来存储Originator类中state变量的临时状态;而Caretaker类就是用来管理备忘录类的,用来向备忘录对象中写入状态或者取回状态。

    多状态多备份备忘录

    通用代码演示的例子中,Originator类只有一个state变量需要备份,而通常情况下,发起人角色通常是一个javaBean,对象中需要备份的变量不止一个,需要备份的状态也不止一个,这就是多状态多备份备忘录。实现备忘录的方法很多,备忘录模式有很多变形和处理方式,像通用代码那样的方式一般不会用到,多数情况下的备忘录模式,是多状态多备份的。其实实现多状态多备份也很简单,最常用的方法是,我们在Memento中增加一个Map容器来存储所有的状态,在Caretaker类中同样使用一个Map容器才存储所有的备份。下面我们给出一个多状态多备份的例子:

    class Originator {
    	private String state1 = "";
    	private String state2 = "";
    	private String state3 = "";
    
    	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;
    	}
    	public Memento createMemento(){
    		return new Memento(BeanUtils.backupProp(this));
    	}
    
    	public void restoreMemento(Memento memento){
    		BeanUtils.restoreProp(this, memento.getStateMap());
    	}
    	public String toString(){
    		return "state1="+state1+"state2="+state2+"state3="+state3;
    	}
    }
    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;
    	}
    }
    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 des: descriptors){
    				String fieldName = des.getName();
    				Method getter = des.getReadMethod();
    				Object fieldValue = getter.invoke(bean, new Object[]{});
    				if(!fieldName.equalsIgnoreCase("class")){
    					result.put(fieldName, fieldValue);
    				}
    			}
    
    		}catch(Exception 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 des: descriptors){
    				String fieldName = des.getName();
    				if(propMap.containsKey(fieldName)){
    					Method setter = des.getWriteMethod();
    					setter.invoke(bean, new Object[]{propMap.get(fieldName)});
    				}
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    class Caretaker {
    	private Map<String, Memento> memMap = new HashMap<String, Memento>();
    	public Memento getMemento(String index){
    		return memMap.get(index);
    	}
    
    	public void setMemento(String index, Memento memento){
    		this.memMap.put(index, memento);
    	}
    }
    class Client {
    	public static void main(String[] args){
    		Originator ori = new Originator();
    		Caretaker caretaker = new Caretaker();
    		ori.setState1("中国");
    		ori.setState2("强盛");
    		ori.setState3("繁荣");
    		System.out.println("===初始化状态===/n"+ori);
    
    		caretaker.setMemento("001",ori.createMemento());
    		ori.setState1("软件");
    		ori.setState2("架构");
    		ori.setState3("优秀");
    		System.out.println("===修改后状态===/n"+ori);
    
    		ori.restoreMemento(caretaker.getMemento("001"));
    		System.out.println("===恢复后状态===/n"+ori);
    	}
    }

    备忘录模式的优缺点和适用场景

    备忘录模式的优点有:

    当发起人角色中的状态改变时,有可能这是个错误的改变,我们使用备忘录模式就可以把这个错误的改变还原。 备份的状态是保存在发起人角色之外的,这样,发起人角色就不需要对各个备份的状态进行管理。

    备忘录模式的缺点:

    在实际应用中,备忘录模式都是多状态和多备份的,发起人角色的状态需要存储到备忘录对象中,对资源的消耗是比较严重的。

    如果有需要提供回滚操作的需求,使用备忘录模式非常适合,比如jdbc的事务操作,文本编辑器的Ctrl+Z恢复等。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    商业智能成CIO优先关注点 技术落地方显成效(1)

    用linux安装MySQL时产生问题破解

    JAVA中关于Map的九大问题

    windows 7旗舰版无法使用远程登录如何开启telnet服务

    Android View 事件分发机制详解

    MySQL用户变量的用法

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。