假如我们已经记录一个人的个人信息,但是发现信息写错了,然后我先备份下再去修改,结果发现原来的信息是正确的,于是我就看备份的个人信息还原到初始的状态,下面我们用代码去实现
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其实就有这种影子。