备忘录(Memento)模式:又叫做快照模式(Snapshot Pattern)或Token模式,属于行为模式。在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
备忘录模式有如下结构图:
备忘录模式涉及角色如下:
发起人(Originator):负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator可以根据需要决定Memento存储自己的哪些内部状态。
备忘录(Memento):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。
管理者(Caretaker):负责备忘录Memento,不能对Memento的内容进行访问或者操作。
对上面结构图的代码模拟:
- package memento;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午2:04:27
- *描述:备忘录角色
- */
- 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 memento;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午2:48:32
- *描述:发起人
- */
- public class Originator {
- private String state;
- public Memento createMemento(){
- return new Memento(state);
- }
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午4:05:39
- *描述:还原
- */
- public void restoreMemento(Memento memento){
- this.state = memento.getState();
- }
- public String getState() {
- return state;
- }
- public void setState(String state) {
- this.state = state;
- }
- }
- package memento;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午2:48:05
- *描述:管理者
- */
- public class Caretaker {
- private Memento memento;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午3:47:18
- *描述:取值
- */
- public Memento retrieveMemento(){
- return memento;
- }
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午4:05:01
- *描述:设置
- */
- public void saveMemento(Memento memento){
- this.memento = memento;
- }
- }
- package memento;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午2:03:49
- *描述:测试类
- */
- public class Client {
- private static Originator o = new Originator();
- private static Caretaker c = new Caretaker();
- /**
- *作者:alaric
- *时间:2013-8-25下午2:03:43
- *描述:
- */
- public static void main(String[] args) {
- //改变发起人的状态
- o.setState("on");
- //创建备忘录对象,并保持于管理保持
- c.saveMemento(o.createMemento());
- //改变发起人的状态
- o.setState("off");
- //还原状态
- o.restoreMemento(c.retrieveMemento());
- }
- }
什么是双接口?就是一个类实现两个接口,不同的类看到的是不同的类型,就像蝙蝠一样,在老鼠一块他就展现的是老鼠的接口;在鸟一块就展现的是鸟的接口。
对于备忘录来说实现双接口,给发起人(Originator)角色展现宽接口,给管理者管理者(Caretaker)提供窄接口。宽接口由Memento本身就可以展现,窄接口只是个标识接口,不提供任何操作的方法。接下来看看如何用双接口方式“ 黑箱”实现。
首先以Memento以标识接口方式提供给除了发起人角色以外的对象,然后把Memento类作为Originaator的内部类,并用private来修饰,保证外部无法操作此类。结构图如下:
描述代码如下:
- package memento.black;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午6:12:48
- *描述:标识接口
- */
- public interface IMemento {
- }
- package memento.black;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午2:48:32
- *描述:发起人
- */
- public class Originator {
- private String state;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午6:18:36
- *描述:穿件备忘录
- */
- public IMemento createMemento(){
- return (IMemento) new Memento(state);
- }
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午4:05:39
- *描述:还原
- */
- public void restoreMemento(IMemento memento){
- Memento m = (Memento) memento;
- setState(m.getState());
- }
- public String getState() {
- return state;
- }
- public void setState(String state) {
- this.state = state;
- System.out.println("current state:"+state);
- }
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午9:22:02
- *描述:内部类
- */
- public class Memento implements IMemento{
- private String state;
- public Memento(String state){
- this.state = state;
- }
- public String getState() {
- return state;
- }
- public void setState(String state) {
- this.state = state;
- }
- }
- }
- package memento.black;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午2:48:05
- *描述:管理者
- */
- public class Caretaker {
- private IMemento memento;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午3:47:18
- *描述:取值
- */
- public IMemento retrieveMemento(){
- return memento;
- }
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午4:05:01
- *描述:设值
- */
- public void saveMemento(IMemento memento){
- this.memento = memento;
- }
- }
- package memento.black;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午2:03:49
- *描述:测试类
- */
- public class Client {
- private static Originator o = new Originator();
- private static Caretaker c = new Caretaker();
- /**
- *作者:alaric
- *时间:2013-8-25下午2:03:43
- *描述:
- */
- public static void main(String[] args) {
- //改变发起人的状态
- o.setState("on");
- //创建备忘录对象,并保持于管理保持
- c.saveMemento(o.createMemento());
- //改变发起人的状态
- o.setState("off");
- //还原状态
- o.restoreMemento(c.retrieveMemento());
- }
- }
current state:on
current state:off
current state:on
举个栗子,数据库系统设定一天一个全备,10分钟一个差备,当数据库系统出现问题的时候,就可以还原最近的一个备份。数据库的备份是一个黑箱的,在没还原之前,一个备份文件我们看不出里面都是什么样的数据,所以这里用黑箱实现来描述,先给出类结构图如下:
描述代码如下:
- package memento.example;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午6:12:48
- *描述:标识接口
- */
- public interface IMemento {
- }
- package memento.example;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午2:48:32
- *描述:数据库系统(发起人角色)
- */
- public class DatabaseServer {
- private boolean isUseable;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午6:18:36
- *描述:穿件备忘录
- */
- public IMemento createMemento(){
- return (IMemento) new Memento(isUseable);
- }
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午4:05:39
- *描述:还原
- */
- public boolean restoreMemento(IMemento memento){
- Memento m = (Memento) memento;
- setUseable(m.isUseable());
- return this.isUseable;
- }
- public boolean isUseable() {
- return isUseable;
- }
- public void setUseable(boolean isUseable) {
- this.isUseable = isUseable;
- System.out.println("DB state useable is: "+isUseable);
- }
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午9:22:02
- *描述:内部类
- */
- public class Memento implements IMemento{
- private boolean isUseable;
- public Memento(boolean isUseable) {
- super();
- this.isUseable = isUseable;
- }
- public boolean isUseable() {
- return isUseable;
- }
- public void setUseable(boolean isUseable) {
- this.isUseable = isUseable;
- }
- }
- }
- package memento.example;
- import java.util.Date;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午2:48:05
- *描述:备份服务器(管理者)
- */
- public class BackupsServer {
- private DatabaseServer dbServer ;//增强管理者的功能,把发起人的操作放在这里
- private Map<Long,IMemento> mementos ;//用一个map来对数据库服务多点备份
- public BackupsServer(DatabaseServer dbServer) {
- super();
- this.dbServer = dbServer;
- mementos = new ConcurrentHashMap<>();
- }
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午3:47:18
- *描述:还原
- */
- public void retrieveMemento(){
- Iterator<Long> it = mementos.keySet().iterator();
- //还原到最近一个可用的状态
- while(it.hasNext()){
- Long key = it.next();
- IMemento val = mementos.get(key);
- boolean isUseable = dbServer.restoreMemento(val);
- if(isUseable){
- break;
- }
- }
- }
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午4:05:01
- *描述:备份
- */
- public void createMemento(){
- IMemento memento = dbServer.createMemento();
- this.mementos.put(new Date().getTime(), memento);
- }
- }
- package memento.example;
- import java.util.Map;
- import memento.Caretaker;
- /**
- *
- *作者:alaric
- *时间:2013-8-25下午2:03:49
- *描述:测试类
- */
- public class Client {
- private static DatabaseServer dbServer = new DatabaseServer();
- private static BackupsServer backupServer = new BackupsServer(dbServer);
- /**
- *作者:alaric
- *时间:2013-8-25下午2:03:43
- *描述:
- * @throws InterruptedException
- */
- public static void main(String[] args) throws InterruptedException {
- //数据库系统设置可用状态
- dbServer.setUseable(true);
- //备份
- backupServer.createMemento();
- //1秒钟备份一次
- Thread.sleep(1000);
- dbServer.setUseable(true);
- backupServer.createMemento();
- Thread.sleep(1000);
- dbServer.setUseable(true);
- backupServer.createMemento();
- Thread.sleep(1000);
- //设置系统故障
- dbServer.setUseable(false);
- //系统故障立即还原到最近一次可用状态
- System.out.println("------系统还原-----");
- backupServer.retrieveMemento();
- }
- }
DB state useable is: true
DB state useable is: true
DB state useable is: true
DB state useable is: false
------系统还原-----
DB state useable is: true
上述代码利用黑箱实现方式模拟了数据库备份还原过程。备忘录模式优点是简化了发起人(Originator)类,它不在需要管理负责备份一个副本在自己内部,当发起人内部状态失效时,可以用外部状态来还原。备忘录模式的缺点是完整保存发起人状态在整个过程中,备忘录角色的资源消耗可能很大,还有就是管理者不知道资源到底多大,外部能不能承担,外部无法预料,也无法给用户一个提醒。
相关推荐
备忘录模式的示例代码和文档,学习备忘录模式的参考资料。
备忘录模式.rar备忘录模式.rar备忘录模式.rar
设计模式之备忘录模式 设计模式之备忘录模式 设计模式之备忘录模式 设计模式之备忘录模式 设计模式之备忘录模式
备忘录模式Demo
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。 备忘录模式java demo
java设计模式-备忘录模式源代码, 源码中为设计模式的工程源文件,已经测试过,没有问题。
设计模式-备忘录模式(讲解及其实现代码)
C#备忘录模式 代码例子 写的比较乱,呵呵
设计模式之备忘录模式的Java版本实现和UML类设计图
本例包含备忘录模式的C#实现,及一个应用案例,加深理解与运用。
备忘录模式C++实现,若理解有误,请留言指出。
备忘录模式在不破坏封装的前提下,记录一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态,本例中设置历次成绩,并记录和保存,最后返回最好成绩
C#面向对象设计模式纵横谈(21):(行为型模式) Memento 备忘录模式
责任链模式 备忘录模式 单(双)链表 显示 "正在加载,请稍后……" 原理 1、责任链模式: * 责任连模式的结构 责任连模式的类图非常简单,它由一个抽象地处理类和它的一组实现类组成: * 抽象处理类:抽象处理类中...
备忘录模式 C++ 实现
在备忘录模式里,一个备忘录是一个对象,它存储另一个对象(备忘录的原发器)在某个瞬间的内部状态。备忘的目的就是为了以后在需要的时候,可以将原发器对象的状态恢复(undo/rollback)到备忘录所保存的状态。 备忘...
Android备忘录模式简单Demo,实现通过memoto备忘录实体,实现游戏存档和读档的功能简单模拟,便于理解备忘录模式.同步博文:http://blog.csdn.net/qq_28690547/article/details/50708415
设计模式之备忘录 和 状态模式精讲 19.1 场景问题 19.1.1 开发仿真系统 考虑这样一个仿真应用,功能是:模拟运行针对某个具体问题的多个解决方案,记录运行过程的各种数据,在模拟运行完成过后,好对这多个解决...