Java 设计模式之备忘录模式的详解(行为模式)

备忘录(Memento)模式:又叫做快照模式(Snapshot Pattern)或Token模式,属于行为模式。在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

备忘录模式有如下结构图:


备忘录模式涉及角色如下:

发起人(Originator:负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator可以根据需要决定Memento存储自己的哪些内部状态。

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

管理者(Caretaker):负责备忘录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 Memento createMemento() {
		return new Memento(state);
	}

	/**
	 * 
	 * 描述:还原
	 */
	public void restoreMemento(Memento memento) {
		this.state = memento.getState();
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}
}
管理者:

public class Caretaker {

	private Memento memento;

	/**
	 * 
	 * 描述:取值
	 */
	public Memento retrieveMemento() {
		return memento;
	}

	/**
	 * 
	 * 描述:设置
	 */
	public void saveMemento(Memento memento) {
		this.memento = memento;
	}
}
测试类:

public class Client {

	private static Originator o = new Originator();
	private static Caretaker c = new Caretaker();

	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来修饰,保证外部无法操作此类。结构图如下:

标识接口:

//标识接口 
public interface IMemento {

}
发起人:

public class Originator {

	private String state;

	/**
	 * 
	 * 描述:穿件备忘录
	 */
	public IMemento createMemento() {
		return (IMemento) new Memento(state);
	}

	/**
	 * 描述:还原
	 */
	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);
	}

	/**
	 * 描述:内部类
	 */
	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;
		}
	}
}
管理者:

public class Caretaker {

	private IMemento memento;

	/**
	 * 描述:取值
	 */
	public IMemento retrieveMemento() {
		return memento;
	}
	/**
	 * 描述:设值
	 */
	public void saveMemento(IMemento memento) {
		this.memento = memento;
	}
}
测试类:

public class Client {

	private static Originator o = new Originator();
	private static Caretaker c = new Caretaker();

	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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值