目录
备忘录模式
引言
现在大多数软件都有撤销功能,快捷键一般都是Ctrl+Z。人们在使用软件的时候,如果出现误操作,则可以使用撤销功能恢复到误操作之前的状态。备忘录模式是软件系统的“月光宝盒”,它提供了一种对象状态的撤销实现机制。
定义
英文定义:“Without violating encapsulation,capture and externalize an object's omtermal state so that the object can be restored to this state later.”。
中文定义:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
备忘录式重要等级★★☆☆☆ 备忘录模式难度等级★★★☆☆
模式结构图
备忘录模式包含如下角色:
1)Originator 原发器
原发器可以创建一个备忘录,存储它的内部状态,也可以使用备忘录恢复历史状态。
2)Memento 备忘录
备忘录存储了原发器的内部状态
3)CareTaker 负责人
负责人只负责保存管理备忘录,而不能操作备忘录。客户端通过负责人间接的访问备忘录。
实例
实例说明
编写一个备忘录接口,使得对象可以实现撤销操作。
实例类图
代码实现
备忘录接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
interface IMemento<T>
{
void RestoreMemento(Memento<int> m);
Memento<T> CreateMemento();
}
备忘录管理者类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BlogDemo
{
class CareTaker<T>
{
private Stack<Memento<T>> mementos = new Stack<Memento<T>>();
public Memento<T> GetMemento()
{
return mementos.Pop();
}
public bool HaveMemento()
{
return mementos.Count > 0;
}
public void SaveMemento(T value)
{
mementos.Push(new Memento<T>(value));
}
}
}
备忘录类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class Memento<T>
{
private T state;
public Memento(T o)
{
state = o;
}
public T GetMemento()
{
return state;
}
}
测试对象类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class TestObj : IMemento<int>
{
int state = 0;
public int State
{
get
{
return state;
}
set
{
state = value;
}
}
public Memento<int> CreateMemento()
{
return new Memento<int>(State);
}
public void RestoreMemento(Memento<int> m)
{
State = m.GetMemento();
}
}
测试代码
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using BlogDemo;
class Program
{
static void Main(string[] args)
{
TestObj o = new TestObj();
CareTaker<int> c = new CareTaker<int>();
for (int i = 0; i < 3; i++)
{
//备份
c.SaveMemento(o.State);
Console.WriteLine("Value is:" + o.State + " Input the increase number:");
o.State += Convert.ToInt16(Console.ReadLine());
}
Console.WriteLine("Value is:" + o.State + "\nHistory values:");
while(c.HaveMemento())
{
//取出备份,并且恢复
o.RestoreMemento(c.GetMemento());
Console.WriteLine("Value is:" + o.State);
}
Console.ReadKey();
}
}
运行截图
模式扩展
备忘录的封装性
为了确保备忘录的封装性,除了原发器外,其他类是不能也不应该访问备忘录类的,在实际开发中,可以通过命名空间的方式来限定。(C++可以使用Frind关键字)。
总结
模式优点
1)提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用先存储起来的备忘录将状态复原。
2)实现了信息的封装,一个备忘录对象是一种原发器对象的表示,不会被其他代码改动,这种模式简化了原发器对象,备忘录只保存原发器的状态。
模式缺点
1)资源消耗大。因为每次保存操作意味着需要分配空间保存历史状态。