设计模式之备忘录模式
Posted 回归心灵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之备忘录模式相关的知识,希望对你有一定的参考价值。
定义
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
通用类图
具体实现
备忘录模式主要是备份对象某一时间的状态,以供后续可能恢复使用。因此有以下几个角色来实现这一功能:发起人角色 Originator、备忘录角色 Memento 和备忘录管理员角色 Caretaker。
发起人角色就是要备份的对象,它负责定义要备份的范围,还要负责创建和恢复备忘录数据,其具体实现如下:
package com.yrs.memento.standard;
/**
* @Author: yangrusheng
* @Description: 发起人角色
* @Date: Created in 17:28 2020/6/21
* @Modified By:
*/
public class Originator
/**
* 内部状态
*/
private String state;
public String getState()
return state;
public void setState(String state)
this.state = state;
/**
* 创建一个备忘录
* @return
*/
public Memento createMemento()
return new Memento(this.state);
/**
* 恢复备数据
* @param memento
*/
public void restoreMemento(Memento memento)
this.setState(memento.getState());
备忘录角色的责任就是要存储备份对象的数据,以便在恢复数据时提供数据。其具体实现如下:
package com.yrs.memento.standard;
/**
* @Author: yangrusheng
* @Description: 备忘录角色
* @Date: Created in 17:35 2020/6/21
* @Modified By:
*/
public 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;
备忘录管理角色的作用是管理备忘录,提供保存和获取备忘录等功能。简单场景下可能看不出太大作用,但是在复杂场景下,上层模块使用备忘录时就会变得麻烦起来,因此通过一个管理类更容易使用。其具体实现如下:
package com.yrs.memento.standard;
/**
* @Author: yangrusheng
* @Description: 备忘录管理员角色
* @Date: Created in 17:36 2020/6/21
* @Modified By:
*/
public class Caretaker
private Memento memento;
public Memento getMemento()
return memento;
public void setMemento(Memento memento)
this.memento = memento;
下面看下场景类如何使用备忘录:
package com.yrs.memento.standard;
/**
* @Author: yangrusheng
* @Description:
* @Date: Created in 18:16 2020/6/21
* @Modified By:
*/
public class Client
public static void main(String[] args)
Originator originator = new Originator();
originator.setState("state1");
System.out.println("init state: " + originator.getState());
// 备份
Caretaker caretaker = new Caretaker();
caretaker.setMemento(originator.createMemento());
// 改变状态
originator.setState("state2");
System.out.println("changed state: " + originator.getState());
// 恢复之前状态
originator.restoreMemento(caretaker.getMemento());
System.out.println("restore state: " + originator.getState());
备忘录模式的使用场景
- 需要保存和恢复数据的相关状态场景。
- 提供一个可回滚的操作。
- 需要监控的副本场景中。
- 数据库连接的事务事务管理。
注意事项:
- 备忘录的生命周期。应该建立就要使用,不使用应立刻删除。
- 备忘录的性能。不要在频繁建立备份的场景中使用备忘录模式。
备忘录模式的扩展
clone 方式的备忘录
发起人角色实现 Cloneable 接口,把备忘录角色和管理者角色都集成到发起人内部,这样就大大简化了备忘录模式的使用。
package com.yrs.memento.clone;
import com.yrs.memento.standard.Memento;
/**
* @Author: yangrusheng
* @Description: 发起人角色
* @Date: Created in 17:28 2020/6/21
* @Modified By:
*/
public class Originator implements Cloneable
private Originator backup;
/**
* 内部状态
*/
private String state;
public String getState()
return state;
public void setState(String state)
this.state = state;
/**
* 创建一个备忘录
*/
public void createMemento()
this.backup = this.clone();
/**
* 恢复备数据
*/
public void restoreMemento()
if (this.backup != null)
this.setState(this.backup.state);
/**
* clone 对象
* @return
*/
@Override
protected Originator clone()
try
return (Originator) super.clone();
catch (CloneNotSupportedException e)
e.printStackTrace();
return null;
多状态的备忘录模式:
当发起人角色有多个状态时,备忘录角色可以使用 HashMap 来存储多个状态,备份和恢复时需要遍历对象的成员变量来一一取值赋值,这里需要一个工具类来做成员变量的取值和赋值,代码具体实现见:
https://github.com/ByrsH/Design-Patterns/tree/master/Design%20Patterns/src/main/java/com/yrs/memento/moreState, 类图如下:
多备份的备忘录
备忘录管理员使用 HashMap 来保存不同版本的备份,保存和读取都有根据版本来操作。详细代码见:https://github.com/ByrsH/Design-Patterns/tree/master/Design%20Patterns/src/main/java/com/yrs/memento/moreBackups
package com.yrs.memento.moreBackups;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: yangrusheng
* @Description: 备忘录管理员角色
* @Date: Created in 17:36 2020/6/21
* @Modified By:
*/
public class Caretaker
private Map<String, Memento> mementoMap = new HashMap<>();
public Memento getMemento(String key)
return mementoMap.get(key);
public void setMemento(String key, Memento memento)
mementoMap.put(key, memento);
备份数据安全性
备份数据是不能被修改的,为了保证其安全性,我们定义一个空备忘录接口,然后在发起人角色内部定义内部类备忘录实现该接口。这样就能保证只有发起人可以修改数据。具体实现见:https://github.com/ByrsH/Design-Patterns/tree/master/Design%20Patterns/src/main/java/com/yrs/memento/security
参考
《设计模式之禅-第2版》
以上是关于设计模式之备忘录模式的主要内容,如果未能解决你的问题,请参考以下文章