备忘录模式(Memento Pattern)
备忘录模式(Memento Pattern)是一种行为型模式,又叫做快照模式(Snapshot Pattern)或Token模式,在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。 备忘录实现了对信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动。备忘录保存了原发器的状态,采用列表、堆栈等集合来存储备忘录对象可以实现多次撤销操作。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication
{
//一般每个接口或类都写在单独的.cs文件中
//本示例为了执行查看方便才写在一起
public class Utils
{
///
/// 反射实现深拷贝
///
/// 传入TIn对象返回TOut对象
///
public static TOut ReflectionClone<TIn, TOut>(TIn tIn)
{
TOut tOut = Activator.CreateInstance<TOut>();
foreach (var itemOut in tOut.GetType().GetProperties())
{
var propIn = tIn.GetType().GetProperty(itemOut.Name);
itemOut.SetValue(tOut, propIn.GetValue(tIn));
}
foreach (var itemOut in tOut.GetType().GetFields())
{
var fieldIn = tIn.GetType().GetField(itemOut.Name);
itemOut.SetValue(tOut, fieldIn.GetValue(tIn));
}
return tOut;
}
/// <summary>
/// 传入List<TIn>,返回List<TOut>
/// </summary>
/// <typeparam name="TIn"></typeparam>
/// <typeparam name="TOut"></typeparam>
/// <param name="tInList"></param>
/// <returns></returns>
public static List<TOut> ReflectionCloneList<TIn, TOut>(List<TIn> tInList)
{
List<TOut> result = new List<TOut>();
foreach (var tIn in tInList)
{
TOut tOut = Activator.CreateInstance<TOut>();
foreach (var itemOut in tOut.GetType().GetProperties())
{
var propIn = tIn.GetType().GetProperty(itemOut.Name);
itemOut.SetValue(tOut, propIn.GetValue(tIn));
}
foreach (var itemOut in tOut.GetType().GetFields())
{
var fieldIn = tIn.GetType().GetField(itemOut.Name);
itemOut.SetValue(tOut, fieldIn.GetValue(tIn));
}
result.Add(tOut);
}
return result;
}
}
public class ContactPerson
{
public string Name { get; set; }
public string MobileNum { get; set; }
}
// 发起人
public class MobileOwner
{
// 发起人需要保存的内部状态
public List<ContactPerson> ContactPersons { get; set; }
public MobileOwner(List<ContactPerson> persons)
{
ContactPersons = persons;
}
// 创建备忘录,将当期要保存的联系人列表导入到备忘录中
public ContactMemento CreateMemento()
{
//深拷贝 参考:https://www.cjavapy.com/article/2494/
return new ContactMemento(Utils.ReflectionCloneList<ContactPerson, ContactPerson>(this.ContactPersons));
}
// 将备忘录中的数据备份导入到联系人列表中
public void RestoreMemento(ContactMemento memento)
{
//深拷贝 参考:https://www.cjavapy.com/article/2494/
this.ContactPersons = Utils.ReflectionCloneList<ContactPerson, ContactPerson>(memento.ContactPersonBack);
}
public void Show()
{
Console.WriteLine("联系人列表中有{0}个人,具体是:", ContactPersons.Count);
foreach (ContactPerson p in ContactPersons)
{
Console.WriteLine("姓名: {0} 号码为: {1}", p.Name, p.MobileNum);
}
}
}
// 备忘录
public class ContactMemento
{
// 保存发起人的内部状态
public List<ContactPerson> ContactPersonBack;
public ContactMemento(List<ContactPerson> persons)
{
ContactPersonBack = persons;
}
}
// 管理角色
public class Caretaker
{
public ContactMemento ContactM { get; set; }
}
class Program
{
static void Main(string[] args)
{
var persons = new List<ContactPerson>
{
new ContactPerson { Name= "C", MobileNum = "13756863001"},
new ContactPerson { Name = "C#", MobileNum = "13756863002"},
new ContactPerson { Name = "Java", MobileNum = "13756863003"}
};
var mobileOwner = new MobileOwner(persons);
mobileOwner.Show();
// 创建备忘录并保存备忘录对象
var caretaker = new Caretaker { ContactM = mobileOwner.CreateMemento() };
// 更改发起人联系人列表
Console.WriteLine("------删除一个联系人------");
mobileOwner.ContactPersons.RemoveAt(2);
mobileOwner.Show();
// 恢复到原始状态
Console.WriteLine("-------恢复联系人列表------");
mobileOwner.RestoreMemento(caretaker.ContactM);
mobileOwner.Show();
Console.Read();
}
}
}