文章转自:汤高的 Java设计模式(十九)—-备忘录模式他的这个文章整理的比较齐全,最重要是知其意。
参考:
JAVA设计模式之:备忘录模式
Java设计模式20-备忘录模式
备忘录模式是一种软件设计模式:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
比如说,我们正在做100个题目,然后做到一半就不想做了,这个时候我们可以把做到哪一题保存起来,下次接着做。
设计模式设计到三个角色:
Memento:
备忘录,负责存储原发者状态的对象。
Caretaker:
负责人,负责管理保存备忘录的对象。
Originator:
原发者,负责创建一个备忘录来记录当前对象的内部状态,并可使用备忘录恢复内部状态。
以一个写作业的案例来写代码
定义一个发起者,内部定义备忘录
package com.madman.base.designMode.memento;
import java.text.MessageFormat;
public class Originator{
/**
* 定义一个数字用来表达做到哪一题了
*/
public int num;
public int getNum() {
return num;
}
/**
* 创建人:madman
* 创建时间:date()
*
* @param num
*/
public void setNum(int num) {
this.num = num;
}
/**
* 创建备忘录
*
* @return
*/
public Memento createMemento() {
return new Memento(this.num);
}
/**
* 恢复备忘录
*
* @param me
*/
public void restoreMemento(Memento me) {
this.num = me.num;
}
/**
* 查看做到哪一题了
*/
public void doNum() {
System.out.println(MessageFormat.format("当前做到第{0}题目了", String.valueOf(num)));
}
}
定义一个备忘录,备忘录的属性就是发起者需要保存的属性
package com.madman.base.designMode.memento;
/**
* 创建备忘录对象
* 这个对象的定义哪些属性 就需要看Originator需要备份哪些属性了
* 这里还是定义num记录做到哪一题了
* <p>
* 直接使用构造方法进行参数赋值了
*/
public class Memento{
public int num;
public Memento(int num) {
this.num = num;
}
public Memento() {
}
public int getNum() {
return num;
}
/**
* 创建人:madman
* 创建时间:date()
*
* @param num
*/
public void setNum(int num) {
this.num = num;
}
}
Caretaker创建一个管理备忘录的保存和恢复
这里的比较简单就是放在内存里面,实际使用应该不会这么潦草。
package com.madman.base.designMode.memento;
/**
* 负责人对象,负责保存和恢复备忘录
* 内部需要定义备忘录属性
*/
public class Caretaker{
Memento me;
public Memento getMe() {
return me;
}
public void saveMemento() {
/**
* 一般而言保存备忘录一般不会放在内里里面
* 写在其他地方的
*/
}
/**
* 创建人:madman
* 创建时间:date()
*
* @param me
*/
public void setMe(Memento me) {
this.me = me;
}
}
Client测试,看下是否恢复到原始状态了
package com.madman.base.designMode.memento;
public class Client{
public static void main(String[] args) {
Caretaker caretaker = new Caretaker();
Memento me = new Memento();
Originator originator = new Originator();
originator.setNum(1);
originator.doNum();
//创建备忘录
Memento memento = originator.createMemento();
originator.setNum(10);
originator.doNum();
//还原备忘录的状态
originator.restoreMemento(memento);
originator.doNum();
}
}
结果
当前做到第1题目了
当前做到第10题目了
当前做到第1题目了
在上述的例子中Memento对象是一个单独的类,并且提供set方法,那么我不就可以调用set方法修改值了,这看着不太好对吧….
要让方法不被调用,只能把方法设置成private的了,但是设置成private,那只能自己访问了,所有我们改成内部类试试..
我们修改下发起者的代码Originator2,大概是这样,这样在外面获取到Memento2 的时候就不能改变他的属性值了。
package com.madman.base.designMode.memento;
import java.text.MessageFormat;
public class Originator2{
/**
* 定义一个数字用来表达做到哪一题了
*/
public int num;
public int getNum() {
return num;
}
/**
* 创建人:madman
* 创建时间:date()
*
* @param num
*/
public void setNum(int num) {
this.num = num;
}
/**
* 创建备忘录
*
* @return
*/
public Memento2 createMemento() {
return new Memento2(this.num);
}
/**
* 恢复备忘录
*
* @param me
*/
public void restoreMemento(Memento me) {
this.num = me.num;
}
/**
* 查看做到哪一题了
*/
public void doNum() {
System.out.println(MessageFormat.format("当前做到第{0}题目了", String.valueOf(num)));
}
class Memento2{
private int num;
private Memento2(int num) {
this.num = num;
}
private Memento2() {
}
private int getNum() {
return num;
}
/**
* 创建人:madman
* 创建时间:date()
*
* @param num
*/
private void setNum(int num) {
this.num = num;
}
}
}
测试还是跟刚才一样的….
除了设置方法和属性为private之外,还可以使用空接口的形式
可参考:汤高的Java设计模式(十九)—-备忘录模式
备忘录模式从另外一个角度上可以理解直接备份整个类,可以把整个类序列化
一下,保存到某个地方,当需要使用的时候直接读出来转成发起者就行,我觉得更方便点..主要还是看应用场景。
备忘录模式的优缺点
优点:
1、备忘录模式可以把发起人内部信息对象屏蔽起来,从而可以保持封装的边界。
2、简化了发起人类。当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
缺点:
1、如果状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象比较昂贵。