设计模式学习之备忘录模式(Memento,行为型模式)(19)

假如我们已经记录一个人的个人信息,但是发现信息写错了,然后我先备份下再去修改,结果发现原来的信息是正确的,于是我就看备份的个人信息还原到初始的状态,下面我们用代码去实现

class Program
    {
        static void Main(string[] args)
        {
            Person person = new Person("张三", "", 25);
        
            //保存内部状态
            Person personBackup = new Person();
            personBackup.Name = person.Name;
            personBackup.Gender = person.Gender;
            personBackup.Age = person.Age;
            person.Show();
            //修改
            person.Name = "李四";
            person.Gender = "";
            person.Age = 20;
            person.Show();
            //回滚还原
            person.Name = personBackup.Name;
            person.Gender = personBackup.Gender;
            person.Age = personBackup.Age;
            person.Show();

        }
    }

    public class Person
    {
        public string Name { get; set; }
        public string Gender { get; set; }
        public int Age { get; set; }

        public Person()
        {
            
        }
        public Person(string name,string gender,int age)
        {
            this.Name = name;
            this.Gender = gender;
            this.Age = age;
        }

        public void Show()
        {
            Console.WriteLine("姓名:{0},性别:{1},年龄:{2}",Name,Gender,Age);
        }

       
    }

运行结果:

虽然功能实现了但是Main函数中要做的事情太多了,违反了类的单一职责原则,下面我们使用备忘录模式来实现

 internal class Program
    {
        private static void Main(string[] args)
        {
            Person person = new Person("张三", "", 25);

            //保存内部状态
            Memento memento = person.CreateMemento();
            person.Show();
            //修改
            person.Name = "李四";
            person.Gender = "";
            person.Age = 20;
            person.Show();
            //回滚还原
            person.SetMemento(memento);
            person.Show();
        }
    }

    public class Person
    {
        public string Name { get; set; }
        public string Gender { get; set; }
        public int Age { get; set; }

        public Person()
        {

        }
        public Person(string name, string gender, int age)
        {
            this.Name = name;
            this.Gender = gender;
            this.Age = age;
        }

        public void Show()
        {
            Console.WriteLine("姓名:{0},性别:{1},年龄:{2}", Name, Gender, Age);
        }

        /// <summary>
        /// 创建一个备份
        /// </summary>
        /// <returns></returns>
        public Memento CreateMemento()
        {
            return new Memento(Name, Gender, Age);
        }

        /// <summary>
        /// 恢复备份
        /// </summary>
        /// <param name="memento">备份的对象</param>
        public void SetMemento(Memento memento)
        {
            this.Name = memento.Name;
            this.Gender = memento.Gender;
            this.Age = memento.Age;
        }

    }

    public class Memento
    {
        public string Name { get; set; }
        public string Gender { get; set; }
        public int Age { get; set; }

        public Memento()
        {

        }
        public Memento(string name, string gender, int age)
        {
            this.Name = name;
            this.Gender = gender;
            this.Age = age;
        }
    }

此时我们通过Person来创建Memento对象来保存Person信息,如果备忘录的东西比较多的话,我们可以通过一个管理者对象Caretaker来管理备忘录对象,改造代码如下:

internal class Program
    {
        private static void Main(string[] args)
        {
            Person person = new Person("张三", "", 25);

            //保存内部状态
            Caretaker caretaker = new Caretaker();
            caretaker.Memento = person.CreateMemento();
            person.Show();
            //修改
            person.Name = "李四";
            person.Gender = "";
            person.Age = 20;
            person.Show();
            //回滚还原
            person.SetMemento(caretaker.Memento);
            person.Show();
        }
    }

    /// <summary>
    /// 原生者
    /// </summary>
    public class Person
    {
        public string Name { get; set; }
        public string Gender { get; set; }
        public int Age { get; set; }

        public Person()
        {

        }
        public Person(string name, string gender, int age)
        {
            this.Name = name;
            this.Gender = gender;
            this.Age = age;
        }

        public void Show()
        {
            Console.WriteLine("姓名:{0},性别:{1},年龄:{2}", Name, Gender, Age);
        }

        /// <summary>
        /// 创建一个备份
        /// </summary>
        /// <returns></returns>
        public Memento CreateMemento()
        {
            return new Memento(Name, Gender, Age);
        }

        /// <summary>
        /// 恢复备份
        /// </summary>
        /// <param name="memento">备份的对象</param>
        public void SetMemento(Memento memento)
        {
            this.Name = memento.Name;
            this.Gender = memento.Gender;
            this.Age = memento.Age;
        }

    }

    /// <summary>
    /// 备忘录
    /// </summary>
    public class Memento
    {
        public string Name { get; set; }
        public string Gender { get; set; }
        public int Age { get; set; }

        public Memento()
        {

        }
        public Memento(string name, string gender, int age)
        {
            this.Name = name;
            this.Gender = gender;
            this.Age = age;
        }
    }

    /// <summary>
    /// 管理者
    /// </summary>
    public class Caretaker
    {
        public Memento Memento { get; set; }
    } 

一、什么是备忘录模式
Memento模式也叫做备忘录模式,是行为型模式的一种,它的作用是保存对象的内部状态,并在需要的时候(undo/rollback)恢复对象以前的状态。
二、备忘录模式的应用场景
如果一个对象需要保存状态并可通过undo或rollback等操作恢复到以前的状态时,可以使用Memento模式。
在实际应用中,备忘录模式都是多状态和多备份的,原生者角色的状态需要存储到备忘录对象中,对资源的消耗是比较严重的。
(1)一个类需要保存它的对象的状态(相当于Originator角色)
(2)设计一个类,该类只是用来保存上述对象的状态(相当于Memento角色)
(3)需要的时候,Caretaker角色要求Originator返回一个Memento并加以保存
(4)undo或rollback操作时,通过Caretaker保存的Memento恢复Originator对象的状态
三、备忘录模式的角色和职责
Originator(原生者)
需要被保存状态以便恢复的那个对象
Memento(备忘录)
该对象由Originator创建,主要用来保存Originator对象的状态。其实这个和克隆很相似,只不过是克隆出来的对象可以拥有对象的接口,而Memento没有。Memento只封装状态,而不再提供其它操作。
Caretaker(管理者)
负责在适当的时间保存/恢复Origniator对象的状态

四、.net中备忘录模式

我们也可以用序列化的方式实现备忘录。序列化之后,我们可以把它临时性保存到数据库、文件、进程内、进程外等地方。ASP.Net的Session其实就有这种影子。 

原文地址:https://www.cnblogs.com/yxlblogs/p/4078478.html