备忘录模式 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.还是老套路,先从名字上来看看."享元"是不是可以这样 ...
随机推荐
- React Native开发 - 搭建React Native开发环境
移动开发以前一般都是原生的语言来开发,Android开发是用Java语言,IOS的开发是Object-C或者Swift.那么对于开发一个App,至少需要两套代码.两个团队.对于公司来说,成本还是有的. ...
- Haskell学习-函数式编程初探
原文地址:Haskell学习-函数式编程初探 为什么要学习函数式编程?为什么要学习Haskell? .net到前端,C#和JavaScript对我来说如果谈不上精通,最起码也算是到了非常熟悉的 ...
- 【JVM虚拟机】(6)---深入理解Class中访问标志、类索引、父类索引、接口索引
JVM(6)访问标志,类索引 上一篇博客讲[JVM虚拟机](5)---深入理解JVM-Class中常量池 我们知道一个class文件正常可以分为7个部分: 魔数与class文件版本 常量池 访问标志 ...
- 基于Jenkins Pipeline的ASP.NET Core持续集成实践
最近在公司实践持续集成,使用到了Jenkins的Pipeline来提高团队基于ASP.NET Core API服务的集成与部署效率,因此这里总结一下. 一.关于持续集成与Jenkins Pipelin ...
- vue全家桶安装以及修改webpack配置新增vue项目启动方式
一.安装node环境(自带npm) 下载地址 二.替换下载源 // 淘宝 NPM 镜像 npm install -g cnpm --registry=https://registry.npm.taob ...
- Windows核心编程第二章,字符串的表示以及宽窄字符的转换
目录 Windows核心编程,字符串的表示以及宽窄字符的转换 1.字符集 1.1.双字节字符集DBCS 1.2 Unicode字符集 1.3 UTF-8编码 1.4 UTF - 32编码. 1.5 U ...
- windows下,读取快捷方式lnk所指向的路径
BOOL GetLnkFileName( OUT PWSTR pLnkName, OUT PWSTR OepnFileNameBuufer, IN DWORD OpenFileNameBufferSi ...
- Java虚拟机一:运行时数据区域
java虚拟机在执行java程序的过程中,会把内存划分为若干个不同的数据区域.每个区域都有各自的用途,创建和销毁时间,按照<java虚拟机规范(Java SE 7 版)>的规定,虚拟机运行 ...
- SQL Server内幕之数据页
数据页是包含已添加到数据库表中的用户数据的结构. 如前所述, 数据页有三种, 每个都以不同的格式存储数据. SQL server 有行内数据页.行溢出数据页和 LOB 数据页. 与 SQL serve ...
- 抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式概述 定义:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类 抽象工厂抽象工厂,顾名思义,就是比工厂模式更抽象的工厂模式.在工厂模式中,一个具体工厂只负责生产一个具体产品 ...