设计模式行为型之备忘录模式
定义
在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以把该对象恢复到原先的状态。
模拟场景
手机联系人备份功能
三个角色
- 发起人角色:记录当前时刻的内部状态,负责创建和恢复备忘录数据。这里就是手机联系人列表对象
- 备忘录角色:负责存储发起人对象的内部状态,在进行恢复时提供给发起人需要的状态。这里是手机联系人列表对象备份对象
- 管理者角色:负责保存备忘录对象。
代码实现
1.手机联系人列表对象
/// <summary> /// 单个联系人 /// </summary> public class LinkUser { /// <summary> /// 用户名 /// </summary> public string UserName { get; set; } /// <summary> /// 手机号 /// </summary> public string MobilePhone { get; set; } } /// <summary> /// 手机通讯录对象 /// </summary> public class AddressBook { public AddressBook() { UserList = new List<LinkUser>(); } /// <summary> /// 联系人列表 /// </summary> public List<LinkUser> UserList { get; set; } /// <summary> /// 显示联系人方法 /// </summary> public void Show() { Console.WriteLine("联系人列表中有{0}个人,他们是:", UserList.Count); foreach (LinkUser p in UserList) { Console.WriteLine("姓名: {0} 号码为: {1}", p.UserName, p.MobilePhone); } }
2.定义一个备忘录对象
/// <summary> /// 通讯录备份 /// </summary> public class AddressBookMemento { public List<LinkUser> UserList { get; set; } public AddressBookMemento(List<LinkUser> userList) { UserList = new List<LinkUser>(); foreach (LinkUser user in userList) { UserList.Add(new LinkUser { UserName = user.UserName, MobilePhone = user.MobilePhone }); }; } }
3.定义管理者角色
// 管理角色 public class Caretaker { // 使用多个备忘录来存储多个备份点 private static Dictionary<string, AddressBookMemento> AddressBookMementoDic = new Dictionary<string, AddressBookMemento>(); public void SaveAddressBookMementoDic(string name, AddressBookMemento addressBookMemento) { AddressBookMementoDic.Add(name, addressBookMemento); } public AddressBookMemento GetAddressBookMementoDic(string name) { if (AddressBookMementoDic.ContainsKey(name)) { return AddressBookMementoDic[name]; } else { throw new Exception("name wrong"); } } }
上端测试代码
static void Main(string[] args) { //初始化一个通讯录 AddressBook book = new AddressBook(); book.UserList.Add(new LinkUser() { UserName = "小红", MobilePhone = "13828320910" }); book.UserList.Add(new LinkUser() { UserName = "小明", MobilePhone = "15828320920" }); book.UserList.Add(new LinkUser() { UserName = "小张", MobilePhone = "15828320931" }); book.Show(); Console.WriteLine("*************************第一次备份成功**************************"); AddressBookMemento addressBookMemento = new AddressBookMemento(book.UserList); Caretaker caretaker = new Caretaker(); caretaker.SaveAddressBookMementoDic("one", addressBookMemento); Console.WriteLine("*************************增加一个联系人**************************"); book.UserList.Add(new LinkUser() { UserName = "李小风", MobilePhone = "18825451242" }); book.Show(); Console.WriteLine("*************************第二次备份**************************"); AddressBookMemento addressBookMementotwo = new AddressBookMemento(book.UserList); Console.WriteLine("*************************恢复到第一次备份**************************"); caretaker.SaveAddressBookMementoDic("two", addressBookMementotwo); { var userList = caretaker.GetAddressBookMementoDic("one").UserList; Console.WriteLine("联系人列表中有{0}个人,他们是:", userList.Count); foreach (LinkUser p in userList) { Console.WriteLine("姓名: {0} 号码为: {1}", p.UserName, p.MobilePhone); } } book.UserList.RemoveAt(0); book.UserList.RemoveAt(0); Console.WriteLine("**********************删除两个*****************************"); book.Show(); Console.WriteLine("**********************恢复到第二次备份*****************************"); { var userList = caretaker.GetAddressBookMementoDic("two").UserList; Console.WriteLine("联系人列表中有{0}个人,他们是:", userList.Count); foreach (LinkUser p in userList) { Console.WriteLine("姓名: {0} 号码为: {1}", p.UserName, p.MobilePhone); } } } }
总结
如果程序中,有类似于要恢复到原来状态的需求可以考虑用备忘录模式来设计。