"围观"设计模式(26)--行为型之备忘录模式(Memento Pattern)

所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。

个人理解

备忘录模式是用于将对象的状态暂存在某些特殊情况下可以将其进行恢复的模式,可以通过多种方式实现,包括clone以及一般方式以及多种参数的备忘录等形式。标准的备忘录在项目中很难直接应用进去,多数为其变形后的处理方式。

备忘录模式角色

备忘录模式主要包含入下几个角色:

Originator: 原发器。负责创建一个备忘录,用以记录当前对象的内部状态,通过也可以使用它来利用备忘录恢复内部状态。同时原发器还可以根据需要决定Memento存储Originator的那些内部状态。

Memento: 备忘录。用于存储Originator的内部状态,并且可以防止Originator以外的对象访问Memento。在备忘录Memento中有两个接口,其中Caretaker只能看到备忘录中的窄接口,它只能将备忘录传递给其他对象。Originator可以看到宽接口,允许它访问返回到先前状态的所有数据。

Caretaker: 负责人。负责保存好备忘录,不能对备忘录的内容进行操作和访问,只能够将备忘录传递给其他对象。

案例解析

案例一:一般备忘录模式

当对象中只有一个参数的时候,使用备忘录模式,保存下当前的状态,交由备忘录类进行暂存,而备忘录对象交由管理员进行管理,当需要进行恢复的时候,直接使用备忘录的管理员进行获取备忘录,设置当前要恢复的对象的属性值就可以了。

主要代码

备忘录的管理员

public class CareTaker {

	private Memento memento;

	public Memento getMemento() {
		return memento;
	}

	public void setMemento(Memento memento) {
		this.memento = memento;
	}

}

备忘录类

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;
	}

}

要进行备忘处理的类

public class Originator {

	private String state = "";

	public String getState() {
		return this.state;
	}

	public void setState(String state) {
		this.state = state;
	}

	public Memento createMemento() {

		return new Memento(this.state);
	}

	public void backState(Memento memento) {
		this.setState(memento.getState());
	}
}

测试类

public class MainTest {

	public static void main(String[] args) {
		Originator orig = new Originator();
		orig.setState("很好");
		System.out.println(orig.getState());

		CareTaker taker = new CareTaker();
		taker.setMemento(orig.createMemento());

		orig.setState("不好");
		System.out.println(orig.getState());

		orig.backState(taker.getMemento());
		System.out.println(orig.getState());
	}
}

案例二:clone实现备忘录模式

将原发器角色和备忘录角色融合为一个角色,通过克隆对象本身实现备份对象的目的。当需要恢复的时候,将克隆的对象的副本中的值取出并进行设置操作就可以了。

主要代码

public class Originator implements Cloneable {

	private Originator orignator;

	private String state = "";

	public String getState() {
		return this.state;
	}

	public void setState(String state) {
		this.state = state;
	}

	public void createMemento() {
		orignator = this.clone();
	}

	public void backState() {
		this.setState(orignator.getState());
	}

	@Override
	protected Originator clone() {
		try {
			return (Originator) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}

}

测试类

public class MainTest {

	public static void main(String[] args) {
		Originator orig = new Originator();
		orig.setState("很好");
		System.out.println(orig.getState());
		orig.createMemento();

		orig.setState("不好");
		System.out.println(orig.getState());

		orig.backState();
		System.out.println(orig.getState());
	}
}

案例三:多种参数的情况下备忘录模式

本例中通过反射技术,获取参数信息,调用其set和get方法分别来设置和获取对象中参数的值,将对象的属性值,封装到HashMap中去,备份的时候通过get读取其值,存储到HashMap中去,回滚的时候将存储的HashMap中的值通过set方法将值设置到原来的属性中去。

此外,备忘录管理员角色,实现了支持版本的备忘录恢复,可以根据具体的需要进行恢复,即:允许恢复到之前的某一个版本。

主要代码

备忘录管理员角色类

public class Caretaker {

	private Map<String, Memento> mementoMap = new HashMap<String, Memento>();

	public Map<String, Memento> getMementoMap() {
		return mementoMap;
	}

	public void setMementoMap(Map<String, Memento> mementoMap) {
		this.mementoMap = mementoMap;
	}

}

备忘录角色类

public class Memento {

	private HashMap<String, Object> stateMap;

	public Memento(HashMap<String, Object> stateMap) {
		this.stateMap = stateMap;
	}

	public HashMap<String, Object> getStateMap() {
		return stateMap;
	}

	public void setStateMap(HashMap<String, Object> stateMap) {
		this.stateMap = stateMap;
	}

}

发起人角色类

public class Originator {

	private String state1 = "";
	private String state2 = "";
	private String state3 = "";

	public String getState1() {
		return state1;
	}

	public void setState1(String state1) {
		this.state1 = state1;
	}

	public String getState2() {
		return state2;
	}

	public void setState2(String state2) {
		this.state2 = state2;
	}

	public String getState3() {
		return state3;
	}

	public void setState3(String state3) {
		this.state3 = state3;
	}

	public Memento createMemento() {

		return new Memento(BeanUtils.store(this));
	}

	public void backState(Memento memento) {

		BeanUtils.back(this, memento.getStateMap());
	}

	@Override
	public String toString() {
		return "Originator [state1=" + state1 + ", state2=" + state2
				+ ", state3=" + state3 + "]";
	}

}

类属性值得存储于恢复辅助类

public class BeanUtils {

	public static HashMap<String, Object> store(Object obj) {

		HashMap<String, Object> stateMap = new HashMap<String, Object>();
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
			PropertyDescriptor[] properties = beanInfo.getPropertyDescriptors();

			for (PropertyDescriptor proper : properties) {

				String propertyName = proper.getName();

				Method readMethod = proper.getReadMethod();

				Object filedValue = readMethod.invoke(obj, new Object[]{});

				if(!propertyName.equalsIgnoreCase("class"))
					stateMap.put(propertyName, filedValue);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return stateMap;
	}

	public static void back(Object obj, HashMap<String, Object> stateMap) {

		try {

			BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
			PropertyDescriptor[] propers = beanInfo.getPropertyDescriptors();

			for (PropertyDescriptor proper : propers) {

				String properName = proper.getName();
				Method method = proper.getWriteMethod();
				if(stateMap.containsKey(properName)) {
					method.invoke(obj, stateMap.get(properName));
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

测试类

public class MainTest {

	public static void main(String[] args) {

		Originator orig = new Originator();
		orig.setState1("很好");
		orig.setState2("很不好");
		orig.setState3("很好");

		HashMap<String, Memento> mementoMap = new HashMap<String, Memento>();

		Caretaker taker = new Caretaker();

		mementoMap.put("001", orig.createMemento());

		orig.setState1("很好");
		orig.setState2("很好");
		orig.setState3("很好");

		mementoMap.put("002", orig.createMemento());

		taker.setMementoMap(mementoMap);

		orig.backState(taker.getMementoMap().get("001"));
		System.out.println(orig);

		orig.backState(taker.getMementoMap().get("002"));
		System.out.println(orig);
	}
}

备忘录模式优点

1、 给用户提供了一种可以恢复状态的机制。可以是用户能够比较方便地回到某个历史的状态。

2、 实现了信息的封装。使得用户不需要关心状态的保存细节。

备忘录模式缺点

消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

备忘录模式应用场景

1、 需要保存一个对象在某一个时刻的状态或部分状态。

2、 如果用一个接口来让其他对象得到这些状态,将会暴露对象的实现细节并破坏对象的封装性,一个对象不希望外界直接访问其内部状态,通过负责人可以间接访问其内部状态。

设计模式代码下载

设计模式源代码下载地址

时间: 2024-10-28 23:42:33

"围观"设计模式(26)--行为型之备忘录模式(Memento Pattern)的相关文章

设计模式(行为型)之备忘录模式(Memento Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(行为型)之中介者模式(Mediator Pattern)>http://blog.csdn.net/yanbober/article/details/45533335 概述 备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无

&quot;围观&quot;设计模式(19)--行为型之观察者模式(Observer Pattern)

观察者模式是软件设计模式的一种.在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知.这通常透过呼叫各观察者所提供的方法来实现.此种模式通常被用来实时事件处理系统.----WIKIPEDIA 个人理解 观察者模式,就是使得被观察者中持有观察者的对象实例,在发生某些事件的时候,通过notify"通知"观察者,完成相应的操作,他也叫作发布-订阅模式,定义对象间一对多的依赖关系,使得被观察者对象产生动作,即可通知其依赖的对象该被观察者发生了变更. 案例

备忘录模式(Memento Pattern)

备忘录模式(Memento Pattern)用来恢复一个对象的状态到以前的状态. 备忘录模式下属于行为模式的类别. 实现实例 在这个示例中,备忘录模式(Memento Pattern)使用三个操作者类. Memento类中包含要恢复的对象的状态. 创建者在Memento对象中创建和存储状态,Caretaker对象负责从Memento中恢复对象状态.在这个示例中,创建了以下几个类:Memento,Originator和CareTaker. MementoPatternDemo这是一个演示类,它将使

&quot;围观&quot;设计模式(18)--行为型之模板方法模式(TemplateMethod Pattern)

模板方法模式定义了一个算法的步骤,并允许子类别为一个或多个步骤提供其实践方式.让子类别在不改变算法架构的情况下,重新定义算法中的某些步骤.----WIKIPEDIA 个人理解 模板方法模式相对而言比较简单,一般的都是由抽象类定义好模板方法,然后,子类通过继承并实现其父类中定义好的模板中需要执行的具体的方法,调用子类对象的模板方法时,会执行该类中的具体实现的方法.这个模式我个人的感觉有点像是面向过程的操作,执行完一道工序,接着下一道工序. 案例解析 模板方法相对来说比较简单,这里只列举一个例子供大

[设计模式] 备忘录模式Memento Pattern

在GOF的<设计模式:可复用面向对象软件的基础>一书中对备忘录模式是这样说的:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 类图和实例: 简单的模式实例: #include <iostream> #include <string> using namespace std; class Memento { private:     string state; public:     Memento(

行为型_备忘录模式(Memento)

作用场景: 当意图在对象外面保存对象的内部状态,但是又不想破坏对象的封装性,就可以考虑备忘录模式. 解释: 其参与者包括 1.Memnto(备忘录,如下列CountMemento ) 2.Originator(原发器,如下列Counter ), 3.Caretaker(管理者,如下列CounterCaretaker ) Memnto用于保存Originator内部状态,其私有窄接口只能有Originator访问,Caretaker只能访问Memnto的宽接口.所以通常Memnto和Origina

用最简单的例子理解备忘录模式(Memento Pattern)

简单来说,备忘录模式就是支持回退操作.假设让一个Notepad支持回退操作,如何实现呢? 首先需要一个备忘录类. public class Memento { private string _msg; public Memento(string msg) { _msg = msg; } public string GetText() { return _msg; } } 以上,○ 构造函数在Nodepad每次记录信息的时候调用,Nodepad所记录的信息最终通过该构造函数赋值给了_msg字段.○

C#面向对象设计之——备忘录模式Memento Pattern(二十三)

一.前言 备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象回复到原先保存的状态. 二.结构图 三.实例代码 using System; using System.Collections.Generic; using System.Text; namespace 备忘录模式 { class Program { static void Main(string[] args) { Originator o = new Originator()

23.备忘录模式(Memento Pattern)

using System; using System.Collections.Generic; namespace ConsoleApplication6 { /// <summary> /// 从字面意思就可以明白,备忘录模式就是对某个类的状态进行保存下来, /// 等到需要恢复的时候, /// 可以从备忘录中进行恢复.生活中这样的例子经常看到, /// 如备忘电话通讯录,备份操作操作系统,备份数据库等. /// </summary> class Program { static