C#设计模式:备忘录模式(Memento Pattern)
一,C#设计模式:备忘录模式(Memento Pattern)
1、发起人角色(Originator):记录当前时刻的内部状态,负责创建和恢复备忘录数据。负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator【发起人】可以根据需要决定Memento【备忘录】存储自己的哪些内部状态。
2、备忘录角色(Memento):负责存储发起人对象的内部状态,在进行恢复时提供给发起人需要的状态,并可以防止Originator以外的其他对象访问备忘录。备忘录有两个接口:Caretaker【管理角色】只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator【发起人】却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。
3、管理者角色(Caretaker):负责保存备忘录对象。负责备忘录Memento,不能对Memento的内容进行访问或者操作。
二,代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace _22.备忘录模式 { /// <summary> /// 部门--需要备份的数据,是状态数据,没有操作 /// </summary> public sealed class Dept { /// <summary> /// 部门 /// </summary> public string DeptName { get; set; } /// <summary> /// 人数 /// </summary> public string Number { get; set; } } /// <summary> /// 发起人--相当于【发起人角色】Originator /// </summary> public sealed class DeptBackOriginator { // 发起人需要保存的内部状态 private List<Dept> _deptList; public List<Dept> DeptList { get { return this._deptList; } set { this._deptList = value; } } /// <summary> /// 初始化需要备份的部门 /// </summary> /// <param name="deptList"></param> public DeptBackOriginator(List<Dept> deptList) { if (deptList != null) { this._deptList = deptList; } else { throw new ArgumentNullException("参数不能为空!"); } } /// <summary> /// 创建备忘录对象实例,将当期要保存的联系人列表保存到备忘录对象中 /// </summary> /// <returns></returns> public DeptMemento CreateMemento() { return new DeptMemento(new List<Dept>(this._deptList)); } /// <summary> /// 将备忘录中的数据备份还原到部门列表中 /// </summary> /// <param name="memento"></param> public void RestoreMemento(DeptMemento memento) { this.DeptList = memento.DeptListBack; } /// <summary> /// 显示备份包含的数据 /// </summary> public void Show() { Console.WriteLine("部门列表中共有{0}个部门,他们是:", DeptList.Count); foreach (Dept p in DeptList) { Console.WriteLine("部门: {0} 人数: {1}", p.DeptName, p.Number); } } } /// <summary> /// 备忘录对象,用于保存状态数据,保存的是当时对象具体状态数据--相当于【备忘录角色】Memeto /// </summary> public sealed class DeptMemento { /// <summary> /// 保存发起人创建的部门数据 /// </summary> public List<Dept> DeptListBack { get; private set; } public DeptMemento(List<Dept> deptList) { DeptListBack = deptList; } } /// <summary> /// 管理角色,它可以管理【备忘录】对象,如果是保存多个【备忘录】对象,当然可以对保存的对象进行增、删等管理处理---相当于【管理者角色】Caretaker /// </summary> public sealed class MementoCaretaker { /// <summary> /// 如果想保存多个【备忘录】对象,通过字典或者堆栈来保存 /// </summary> public Dictionary<string, DeptMemento> DeptMementoDictionary { get; set; } /// <summary> /// 单个备份点 /// </summary> public DeptMemento DeptMemento { get; set; } public MementoCaretaker() { DeptMementoDictionary = new Dictionary<string, DeptMemento>(); } } class Program { static void Main(string[] args) { List<Dept> dept = new List<Dept>() { new Dept() { DeptName="技术部", Number = "15987487456"}, new Dept() { DeptName="人事部", Number = "15987487457"}, new Dept() { DeptName="产品部", Number = "15987487458"} }; #region 单个备份点 //手机名单发起人 DeptBackOriginator mobileOriginator = new DeptBackOriginator(dept); mobileOriginator.Show(); // 创建备忘录并保存备忘录对象 MementoCaretaker manager = new MementoCaretaker(); manager.DeptMemento = mobileOriginator.CreateMemento(); ///创建第一个备份点 manager.DeptMementoDictionary.Add("One", mobileOriginator.CreateMemento()); // 更改发起人联系人列表 Console.WriteLine("----移除最后一个联系人--------"); mobileOriginator.DeptList.RemoveAt(2); mobileOriginator.Show(); ///创建第二个备份点 Thread.Sleep(1000); //等待10秒 manager.DeptMementoDictionary.Add("Two", mobileOriginator.CreateMemento()); // 恢复到原始状态 Console.WriteLine("-------恢复联系人列表------"); mobileOriginator.RestoreMemento(manager.DeptMemento); mobileOriginator.Show(); #endregion #region 多个备份点 Console.WriteLine("-------输出两个备份点------"); ////输出备份点 foreach (var item in manager.DeptMementoDictionary) { mobileOriginator.RestoreMemento(item.Value); mobileOriginator.Show(); } Console.WriteLine("-------恢复到第一个备份点------"); mobileOriginator.RestoreMemento(manager.DeptMementoDictionary["One"]); mobileOriginator.Show(); Console.WriteLine("-------恢复到第二个备份点------"); mobileOriginator.RestoreMemento(manager.DeptMementoDictionary["Two"]); mobileOriginator.Show(); #endregion Console.Read(); } } }