备忘录模式 Memento 快照模式 标记Token模式 行为型 设计模式(二十二)
意图
结构
- 备忘录模式通过引入备忘录Memento记录对象的内部状态
- 引入管理员CareTaker对备忘录进行管理
- 控制访问--原发器Originator与备忘录对象进行交互,其他所有地方都只是获取传递,不更改设置Memento的状态
代码示例
一个简单的快照实现
快照信息保存在备忘录Memento中
通过管理员CareTaker进行保管
package memento.simple;
/**
* 业务逻辑类,也就是我们需要备份的对象
* 内部拥有state属性,用来表示快照需要保存的状态数据
*/
public class Originator {
private Integer state;
/**
* 创建快照备份
* @return
*/
public Memento createMemento() {
return new Memento(state);
}
/**
* 恢复快照
* @param memento
*/
public void recovery(Memento memento) {
state = memento.getState();
} public Integer getState() {
return state;
} public void setState(Integer state) {
this.state = state;
} @Override
public String toString() {
final StringBuilder sb = new StringBuilder("Originator{");
sb.append("state=").append(state);
sb.append('}');
return sb.toString();
}
}
package memento.simple;
/**
* 备忘录类用来保存业务逻辑对象的状态(原发器)
* 备忘录类的属性要参考原发器的设计,确定需要保存哪些数据信息
* 此处我们以state为演示
* 备忘录类提供了getter和setter方法
*/
public class Memento {
private Integer state;
Memento(Integer state) {
this.state = state;
} public Integer getState() {
return state;
} public void setState(Integer state) {
this.state = state;
}
}
package memento.simple;
/**
* 管理员类,内部拥有一个memento,可以设置和获取这个属性
*/
public class CareTaker { private Memento memento;
public Memento getMemento() {
return memento;
} public void setMemento(Memento memento) {
this.memento = memento;
}
}
package memento.simple;
public class Test { public static void main(String[] args) { //创建业务逻辑对象,设置状态信息
Originator originator = new Originator();
originator.setState(2); //快照
Memento memento = originator.createMemento();
CareTaker careTaker = new CareTaker();
careTaker.setMemento(memento); System.out.println("初始时状态: " + originator.toString()); originator.setState(3);
System.out.println("更新状态后: " + originator.toString()); originator.setState(8);
System.out.println("更新状态后: " + originator.toString()); originator.setState(6);
System.out.println("更新状态后: " + originator.toString()); originator.recovery(careTaker.getMemento());
System.out.println("恢复状态后: " + originator.toString());
}
}
- Memento备忘录对来自Originator的修改开放(比如上面的Originator可以创建Memento)
- Memento备忘录对来自CareTaker的修改开放(上面示例中,仅仅传递Memento,不曾访问内部细节)
内部类方式重构
package memento;
public interface MementoInterface {
}
package memento;
/**
* 业务逻辑类,也就是我们需要备份的对象 内部拥有state属性,用来表示快照需要保存的状态数据
*/
public class Originator {
private Integer state;
/**
* 创建快照备份返回标记接口,以使外界不能操作备忘录
*/
public Memento createMemento() {
return new Memento(state);
}
/**
* 恢复快照,接受MementoInterface类型参数 使用时强转为内部类Memento
*/
public void recovery(MementoInterface memento) {
state = ((Memento) memento).getState();
}
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
}
/**
* 私有内部类,实现MementoInterface接口,标记接口 用以外界交互,达到对外界close的效果
*/
private class Memento implements MementoInterface {
private Integer state; Memento(Integer state) {
this.state = state;
} public Integer getState() {
return state;
} public void setState(Integer state) {
this.state = state;
}
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Originator{");
sb.append("state=").append(state);
sb.append('}');
return sb.toString();
}
}
package memento;
/**
* 管理员类,内部拥有一个 MementoInterface,可以设置和获取这个属性
*/
public class CareTaker {
private MementoInterface memento;
public MementoInterface getMemento() {
return memento;
}
public void setMemento(MementoInterface memento) {
this.memento = memento;
}
}
时序图
- 客户端程序对原发器Originator进行状态设置
- 客户端程序对原发器进行快照创建
- 客户端程序对快照进行保存
- 客户端程序获得快照
- 客户端程序根据快照进行状态恢复
重构小结
- 借助于私有内部类实现了对外界的封闭
- 将负责人管理员CareTaker与Memento进行解耦,通过抽象MementoInterface进行连接
形式变换
package memento.refactor1;
/**
* 管理员类,内部拥有一个 MementoInterface,可以设置和获取这个属性
*/
public class CareTaker { private MementoInterface memento;
private Originator originator; CareTaker(Originator originator) {
this.originator = originator;
} /**
* 创建快照,借助于内部的Originator
*/
public MementoInterface createMemento() {
return originator.createMemento();
} /**
* 恢复快照,借助于内部的Originator
*/
public void recovery(MementoInterface memento) {
originator.recovery(memento);
}
public MementoInterface getMemento() {
return memento;
}
public void setMemento(MementoInterface memento) {
this.memento = memento;
}
}
public static void main(String[] args) {
Memento memento = originator.createMemento();
originator.recovery(originator.recovery();
}
与命令模式的联系
总结
备忘录模式 Memento 快照模式 标记Token模式 行为型 设计模式(二十二)的更多相关文章
- Java设计模式(十二) 策略模式
原创文章,同步发自作者个人博客,http://www.jasongj.com/design_pattern/strategy/ 策略模式介绍 策略模式定义 策略模式(Strategy Pattern) ...
- 解释器模式 Interpreter 行为型 设计模式(十九)
解释器模式(Interpreter) 考虑上图中计算器的例子 设计可以用于计算加减运算(简单起见,省略乘除),你会怎么做? 你可能会定义一个工具类,工具类中有N多静态方法 比如定义了两个 ...
- 命令模式 Command 行为型 设计模式(十八)
命令模式(Command) 请分析上图中这条命令的涉及到的角色以及执行过程,一种可能的理解方式是这样子的: 涉及角色为:大狗子和大狗子他妈 过程为:大狗子他妈角色 调用 大狗子的“回家吃饭”方法 引子 ...
- 桥接模式 桥梁模式 bridge 结构型 设计模式(十二)
桥接模式Bridge Bridge 意为桥梁,桥接模式的作用就像桥梁一样,用于把两件事物连接起来 意图 将抽象部分与他的实现部分进行分离,使得他们都可以独立的发展. 意图解析 依赖倒置原 ...
- C#设计模式之二十二备忘录模式(Memento Pattern)【行为型】
一.引言 今天我们开始讲“行为型”设计模式的第十个模式,该模式是[备忘录模式],英文名称是:Memento Pattern.按老规矩,先从名称上来看看这个模式,个人的最初理解就是对某个对象的状态进行保 ...
- C#设计模式之二十二备忘录模式(Memeto Pattern)【行为型】
一.引言 今天我们开始讲"行为型"设计模式的第十个模式,该模式是[备忘录模式],英文名称是:Memento Pattern.按老规矩,先从名称上来看看这个模式,个人的最初理解就 ...
- Java进阶篇设计模式之十二 ---- 备忘录模式和状态模式
前言 在上一篇中我们学习了行为型模式的策略模式(Strategy Pattern)和模板模式(Template Pattern).本篇则来学习下行为型模式的两个模式,备忘录模式(Memento Pat ...
- Java设计模式之十二 ---- 备忘录模式和状态模式
前言 在上一篇中我们学习了行为型模式的策略模式(Strategy Pattern)和模板模式(Template Pattern).本篇则来学习下行为型模式的两个模式,备忘录模式(Memento Pat ...
- C#设计模式之十二享元模式(Flyweight)【结构型】
一.引言 今天我们要讲[结构型]设计模式的第六个模式,该模式是[享元模式],英文名称是:Flyweight Pattern.还是老套路,先从名字上来看看."享元"是不是可以这样 ...
随机推荐
- PHP全栈学习笔记13
php与ajax技术 web2.0的到来,ajax逐渐成为主流,什么是ajax,ajax的开发模式,优点,使用技术.(ajax概述,ajax使用的技术,需要注意的 问题,在PHP应用ajax技术的应用 ...
- 跟我一起学opencv 第四课之图像的基本操作
1.图像是由像素组成的,所以修改了像素就可以实现图像的改变. 2先看灰度图像(单通道): *****2.获取灰度图像的像素值使用: int gray = gray_src.at<uchar&g ...
- WAF开放规则定义权:专家策略+用户自定义策略=Web安全
在第一期“漫说安全”栏目中,我们用四格漫画的形式介绍了基于深度学习的阿里云WAF到底智能在哪里,能帮客户解决什么问题. 在今天的这期栏目里,我们依然通过漫画这种通俗易懂的方式,与大家分享阿里云WAF的 ...
- Django-restframework 之认证源码分析
Django-restframework 源码分析之认证 前言 最近学习了 django 的一个 restframework 框架,对于里面的执行流程产生了兴趣,经过昨天一晚上初步搞清楚了执行流程(部 ...
- 立即执行函数 IIFE
立即执行函数表达式IIFE(Immediately-invoked function expression)我们知道,在javascript(ES5)中,是没有块级作用域的概念的.看一个例子 for ...
- K3数据字典备查
select distinct f.FNumber as 系统代码, f.FName AS 系统名称, d.FTableName AS 表名,d.FDescription AS 表说明,a.[nam ...
- ArcEngine GroupLayer监听图层改变
最近项目中需要用到在TOC监听图层的变化,从而针对添加的不同图层进行不同的操作.但是当TOC中添加图层组时,无法监听到图层组中添加图层的动作.也就无法获取到向图层组中添加的图层. 在开发手册中也没有找 ...
- Git:三、工作原理
首先,我们对工作区也就是文件夹中的文档进行修改. 然后,把修改并需要存档的文档用add命令放到暂存区,并且可以放很多文档. 最后,一个阶段的工作告一段落,使用commit命令把暂存区的内容一股脑存到G ...
- MongoDB十二种最有效的模式设计【转】
持续关注MongoDB博客(https://www.mongodb.com/blog)的同学一定会留意到,技术大牛Daniel Coupal 和 Ken W. Alger ,从 今年 2月17 号开始 ...
- Beyond Compare 3.3.8 build 16340 + Key
本文摘录自冰点社区:http://forum.z27315.com/topic/14746-beyond-compare-338-build-16340-key/ Download Beyond Co ...