设计模式(Design pattern)是代码设计经验的总结。设计模式主要分三个类型:创建型、结构型和行为型。创建型是对象实例化的模式,创建型模式用于解耦对象的实例化过程,主要用于创建对象。结构型是把类或对象结合在一起形成一个更大的结构,主要用于优化不同类、对象、接口之间的结构关系。行为型是类和对象如何交互,及划分责任和算法。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。本文主要介绍.NET(C#) 设计模式 备忘录模式。

备忘录模式(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();
        }
    }
}

推荐文档