备忘录模式 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.还是老套路,先从名字上来看看."享元"是不是可以这样 ...
随机推荐
- go语言调度器源代码情景分析之一:开篇语
专题简介 本专题以精心设计的情景为线索,结合go语言最新1.12版源代码深入细致的分析了goroutine调度器实现原理. 适宜读者 go语言开发人员 对线程调度器工作原理感兴趣的工程师 对计算机底层 ...
- asp.net core系列 47 Identity 自定义用户数据
一.概述 接着上篇的WebAppIdentityDemo项目,将自定义用户数据添加到Identity DB,自定义扩展的用户数据类应继承IdentityUser类, 文件名为Areas / Ident ...
- 带着新人看java虚拟机04(多线程篇)
我记得最开始接触多进程,多线程这一块的时候我不是怎么理解,为什么要有多线程啊?多线程到底是个什么鬼啊?我一个程序好好的就可以运行为什么要用到多线程啊?反正我是十分费解,即使过了很长时间我还是不是很懂, ...
- JSON Web Token入门教程
目录 一.跨域认证的问题 二.JWT的原理 三.JWT的数据结构 3.1Header 3.2Payload 3.3 Signature 3.4 Base64URL 四.JWT的使用方式 五.JWT的几 ...
- Android 6.0 默认关闭定位和GPS,开启后默认选省电
默认关闭定位和GPS 修改位置 frameworks/base/packages/SettingsProvider/res/values/defaults.xml <string name=&q ...
- 一起学Android之Storage
概述 在Android开发中,存储(Storage)的方式根据具体的需求不同而不同,例如数据对应用程序是私有的还是其他应用程序(和用户)可以访问的,以及保存数据需要多大的空间. 存储分类 主要的存储方 ...
- github常见操作和常见错误!错误提示:fatal: remote origin already exist
如果输入$ git remote add origin git@github.com:djqiang(github帐号名)/gitdemo(项目名).git 提示出错信息:fatal: remote ...
- centos7.3 kubernetes/k8s 1.10 离线安装 --已验证
本文介绍在centos7.3使用kubeadm快速离线安装kubernetes 1.10. 采用单master,单node(可以多node),占用资源较少,方便在笔记本或学习环境快速部署,不适用于生产 ...
- .NET Core 2.1来了!
太棒了! .NET Core 2.0正式发布至今已经过去了大半年,这大半年说长不长说短不短,这段时间里,我是充分地体会到了微软的诚意,那就是认认真真打造一个优秀的开源平台.这大半年的时间里,微软一直在 ...
- POST不同提交方式对应的Content-Type,及java服务器接收参数方式
POST不同提交方式对应的Content-Type,及java服务器接收参数方式 注:本博客参考了网上的文章结合自己工作总结后所写,主要用于记录自己工作所得,如有错误请批评指正. 简介: Conten ...