`
zzq19860626
  • 浏览: 261137 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
博客专栏
B20df9e2-fb3d-3644-9f72-c1619842f682
设计模式学习笔记
浏览量:178034
87eaf24f-812a-3463-8e65-e3197d2ad8c2
java虚拟机
浏览量:26210
社区版块
存档分类
最新评论

JAVA设计模式学习22——备忘录模式

阅读更多
备忘录(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());
	}

}
 对于上述描述中,客户端语句o.createMemento()得到备忘录后,是可以直接获取备忘录中信息的,因为备忘录类没有提供窄接口,这样就破坏了原有的封装性。这种设计备忘录角色的内部所存状态对所有对象是公开的,所以叫做"白箱"实现。有白箱就有黑箱,“黑箱”的实现方式就是利用java双接口的方式来隔离不同的对象访问的。
 
什么是双接口?就是一个类实现两个接口,不同的类看到的是不同的类型,就像蝙蝠一样,在老鼠一块他就展现的是老鼠的接口;在鸟一块就展现的是鸟的接口。

 对于备忘录来说实现双接口,给发起人(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)类,它不在需要管理负责备份一个副本在自己内部,当发起人内部状态失效时,可以用外部状态来还原。备忘录模式的缺点是完整保存发起人状态在整个过程中,备忘录角色的资源消耗可能很大,还有就是管理者不知道资源到底多大,外部能不能承担,外部无法预料,也无法给用户一个提醒。

 

 设计模式系列目录:

  • 大小: 15.6 KB
  • 大小: 4.8 KB
  • 大小: 10.7 KB
  • 大小: 23.6 KB
6
2
分享到:
评论

相关推荐

    java和设计模式ppt教程

    java和设计模式ppt包含工厂模式、建造模式、原始模型模式、单例模式、结构模式、适配器、桥梁模式、合成模式、装饰模式、门面模式、享元模式、代理模式、行为模式、解释器模式、迭代子模式、调停者模式、备忘录模式...

    Java设计模式 版本2

    Java设计模式,目录:前言,UML建模技术,深入浅出UML类图,从招式与内功谈起——设计模式概述,面向对象设计原则,工厂三兄弟之简单工厂模式,工厂三兄弟之工厂方法模式,工厂三兄弟之抽象工厂模式,确保对象的唯一...

    java设计模式

    目录: 前 言 第一部分 大旗不挥,谁敢冲锋——热身篇 第1章 单一职责原则 1.1 我是“牛”类,我可以担任多职吗 1.2 绝杀技,打破你的传统思维 1.3 我单纯,所以我快乐 1.4 最佳实践 ...附录:23个设计模式

    design-pattern-java.pdf

    设计模式趣味学习(复习) 设计模式趣味学习(复习) 设计模式与足球(一) 设计模式与足球(二) 设计模式与足球(三) 设计模式与足球(四) 设计模式综合应用实例 设计模式综合应用实例 多人联机射击游戏 多人...

    深入浅出设计模式(中文版电子版)

    5.6MementoPattern(备忘录模式) 223 5.6.1定义 223 5.6.2现实示例——音响均衡器 226 5.6.3C#实例——销售目标 226 5.6.4Java实例——多次Undo(取消)操作 231 5.6.5优势和缺陷 236 5.6.6应用情景 236 5.7...

    深入浅出设计模式(中文版)

    5.6MementoPattern(备忘录模式) 223 5.6.1定义 223 5.6.2现实示例——音响均衡器 226 5.6.3C#实例——销售目标 226 5.6.4Java实例——多次Undo(取消)操作 231 5.6.5优势和缺陷 236 5.6.6应用情景 236 5.7...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷6

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷8

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    【白雪红叶】JAVA学习技术栈梳理思维导图.xmind

    备忘录模式 观察者模式 状态模式 策略模式 模板方法模式 访问者模式 设计案例 UML 架构 系统架构能力 基本理论 扩展性设计 可用性设计 可靠性设计 一致性设计 负载均衡设计 过载保护设计 协议设计...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷3

    pattern/src/behavior/memento //13.7备忘录模式 pattern/src/behavior/state //13.8状态模式 pattern/src/behavior/visitor //13.9访问者模式 pattern/src/behavior/mediator //13.10中介者模式 pattern/src/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷1

    pattern/src/behavior/memento //13.7备忘录模式 pattern/src/behavior/state //13.8状态模式 pattern/src/behavior/visitor //13.9访问者模式 pattern/src/behavior/mediator //13.10中介者模式 pattern/src/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷9

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    设计模式Demo

    行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。 其实还有两类:并发型模式和线程池模式。 二、设计...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷10

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷5

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷7

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷2

    pattern/src/behavior/memento //13.7备忘录模式 pattern/src/behavior/state //13.8状态模式 pattern/src/behavior/visitor //13.9访问者模式 pattern/src/behavior/mediator //13.10中介者模式 pattern/src/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷4

    pattern/src/behavior/memento //13.7备忘录模式 pattern/src/behavior/state //13.8状态模式 pattern/src/behavior/visitor //13.9访问者模式 pattern/src/behavior/mediator //13.10中介者模式 pattern/src/...

    java面试题及技巧4

    基于MVC的.java.web设计与开发.pdf │ 学习Struts提供的和Form相关标签.txt │ 日企编码规范.doc │ 电信盈科面试题.pdf │ 速算.txt │ 面试题URL.txt │ ├─Javascript │ │ javascript资料(源码,教材,ppt)....

Global site tag (gtag.js) - Google Analytics