设计模式行为型之备忘录模式


定义

在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以把该对象恢复到原先的状态。

模拟场景

手机联系人备份功能

三个角色

  • 发起人角色:记录当前时刻的内部状态,负责创建和恢复备忘录数据。这里就是手机联系人列表对象
  • 备忘录角色:负责存储发起人对象的内部状态,在进行恢复时提供给发起人需要的状态。这里是手机联系人列表对象备份对象
  • 管理者角色:负责保存备忘录对象。

代码实现

1.手机联系人列表对象

/// 
    /// 单个联系人
    /// 
    public class LinkUser
    {
        /// 
        /// 用户名
        /// 
        public string UserName
        {
            get;
            set;
        }

        /// 
        ///  手机号
        /// 
        public string MobilePhone
        {
            get;
            set;
        }
    }

    /// 
    /// 手机通讯录对象
    /// 
    public class AddressBook
    {
        public AddressBook()
        {
            UserList = new List();
        }
       /// 
       /// 联系人列表
       /// 
        public List UserList
        {
            get;
            set;
        }
        
        /// 
        /// 显示联系人方法
        /// 
        public void Show()
        {
            Console.WriteLine("联系人列表中有{0}个人,他们是:", UserList.Count);
            foreach (LinkUser p in UserList)
            {
                Console.WriteLine("姓名: {0} 号码为: {1}", p.UserName, p.MobilePhone);
            }
        }

2.定义一个备忘录对象

    /// 
    /// 通讯录备份
    /// 
    public class AddressBookMemento
    {
        public List UserList { get; set; }
        public AddressBookMemento(List userList)
        {
            UserList = new List();
            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);
                }
            }

        }
    }

总结

如果程序中,有类似于要恢复到原来状态的需求可以考虑用备忘录模式来设计。