备忘录模式

为什么引入备忘录模式

在我们的生活中,不可能一番风顺,也会犯错,但是如果可以向word那样,做错了就撤销,回到原来的样子,那就更棒了,又例如数据库,当数据库被破坏,我们通常的做法是从日志中找出原因,如果可以进行恢复,更好,如果不能恢复,我们会将以前备份的数据库迁移过来,然后从数据库日志中查看接下来要执行什么事务,来尽可能的恢复到原来的数据库,在这两种情况下,我们都需要回到事物原来的某个时刻的状态,这就需要备忘录模式。

备忘录模式是什么

再不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。

核心思想

在目标类内部创建备份,有一个备份类用于记录目标类的状态,备份管理类则用于得到和设置备份类。

具体案例

时光倒流,遇到18岁的你,使用备忘录模式,

UML

代码

package com.dong.MementoM;

public class Human {
	
	private String name;
	private int age;
	
	public Human(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	//进行备份
	public Memento saveTime() {
		return new Memento(this.name,this.age);
	}
	//从备份中获取对象属性,进行赋值
	public void TimeReturn(Memento p) {
		this.name = p.getName();
		this.age = p.getAge();
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Human [name=" + name + ", age=" + age + "]";
	}
}

package com.dong.MementoM;

public class Memento {
	
	private String name;
	private int age;
	
	public Memento(String name, int age) {
		this.name = name;
		this.age = age;
	}	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}		
}	

package com.dong.MementoM;

public class MementoCareTaker {
	
	private Memento memento ;

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

package com.dong.MementoM;
/**
 *  Human [name=DL, age=17]
	一年后
	Human [name=DL, age=18]
	两年后
	Human [name=DL, age=20]
	回到18岁
	Human [name=DL, age=18]
 * @author liuD
 */
public class client {
	public static void main(String[] args) throws InterruptedException {
		MementoCareTaker mct = new MementoCareTaker();
		Human human = new Human("DL", 17);
		System.out.println(human);
		System.out.println("一年后");
		Thread.sleep(1000);
		human.setAge(18);
		System.out.println(human);
		mct.setMemento(human.saveTime());
		System.out.println("两年后");
		Thread.sleep(2000);
		human.setAge(20);
		System.out.println(human.toString());
		System.out.println("回到18岁");
		human.TimeReturn(mct.getMemento());
		System.out.println(human.toString());
	}
}

优点

从结构中可以看到类与类之间的低耦合,各司其职,管理明确,

扩展:

多备份备录模式:

在备忘录管理者类中使用HashMap记录目标的多个状态,

部分修改代码:

package com.dong.MementoM;

import java.util.HashMap;

public class MementoCareTaker {

	private HashMap<String,Memento> memMap = new HashMap<String,Memento>();
	
	public Memento getMemento(String id) {
		return memMap.get(id);
	}
	public void setMemento(String id,Memento memento) {
		memMap.put(id, memento);
	}
}

package com.dong.MementoM;
/**
Human [name=DL, age=17]
一年后
Human [name=DL, age=18]
两年后
Human [name=DL, age=20]
回到18岁
Human [name=DL, age=18]
回到20岁
Human [name=DL, age=20]
 * @author liuD
 */
public class client {
	public static void main(String[] args) throws InterruptedException {
		MementoCareTaker mct = new MementoCareTaker();
		Human human = new Human("DL", 17);
		System.out.println(human);
		System.out.println("一年后");
		Thread.sleep(1000);
		human.setAge(18);
		System.out.println(human);
		mct.setMemento("001" ,human.saveTime());
		System.out.println("两年后");
		Thread.sleep(2000);
		human.setAge(20);
		mct.setMemento("002" ,human.saveTime());
		System.out.println(human.toString());
		System.out.println("回到18岁");
		human.TimeReturn(mct.getMemento("001"));
		System.out.println(human.toString());
		System.out.println("回到20岁");
		human.TimeReturn(mct.getMemento("002"));
		System.out.println(human.toString());	
	}
}