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

class Program
{
static void Main(string[] args)
{
Person person = new Person("张三", "男", ); //保存内部状态
Person personBackup = new Person();
personBackup.Name = person.Name;
personBackup.Gender = person.Gender;
personBackup.Age = person.Age;
person.Show();
//修改
person.Name = "李四";
person.Gender = "女";
person.Age = ;
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("张三", "男", ); //保存内部状态
Memento memento = person.CreateMemento();
person.Show();
//修改
person.Name = "李四";
person.Gender = "女";
person.Age = ;
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("张三", "男", ); //保存内部状态
Caretaker caretaker = new Caretaker();
caretaker.Memento = person.CreateMemento();
person.Show();
//修改
person.Name = "李四";
person.Gender = "女";
person.Age = ;
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其实就有这种影子。

设计模式学习之备忘录模式(Memento,行为型模式)(19)的更多相关文章

  1. 设计模式学习之单例模式(Singleton,创建型模式)(4)

    假如程序中有一个Person类,我的需求就是需要在整个应用程序中只能new一个Person,而且这个Person实例在应用程序中进行共享,那么我们该如何实现呢? 第一步: 新建一个Person类,类中 ...

  2. 设计模式学习之观察者模式(Observer,行为型模式)(7)

    1.观察者模式又叫做发布-订阅模式. 2.观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 3 ...

  3. 设计模式20:Memento 备忘录模式(行为型模式)

    Memento 备忘录模式(行为型模式) 对象状态的回溯 对象状态的变化无端,如何回溯.恢复对象在某个点的状态? 动机(Motivation) 在软件构建过程中,某些对象的状态在转换过程中,可能由于某 ...

  4. 设计模式17:Iterator 迭代器模式(行为型模式)

    Iterator 迭代器模式(行为型模式) 动机(Motivation) 在软件构建过程中,集合对象内部结构常常变化各异.但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码可以透 ...

  5. 设计模式16:Mediator 中介者模式(行为型模式)

    Mediator 中介者模式(行为型模式) 依赖关系的转化 动机(Motivation) 在软件构建过程中,经常出现多个对象互相关联交互的情况,对象之间经常会维持一种复杂的应用关系,如果遇到一些需求的 ...

  6. 设计模式23:Visitor 访问者模式(行为型模式)

    Visitor 访问者模式(行为型模式) 动机(Motivation)在软件构造过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的修改,将会给子类带来繁重的 ...

  7. 设计模式22:Strategy 策略模式(行为型模式)

    Strategy 策略模式(行为型模式) 动机(Motivation) 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂:而且有时候支持 ...

  8. 设计模式21:State 状态模式(行为型模式)

    State 状态模式(行为型模式) 动机(Motivation) 在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态的行为就可能完全不同. ...

  9. 设计模式19:Chain Of Responsibility 职责链模式(行为型模式)

    Chain Of Responsibility 职责链模式(行为型模式) 请求的发送者与接受者 某些对象请求的接受者可能有多种多样,变化无常…… 动机(Motivation) 在软件构建过程中,一个请 ...

  10. 设计模式15:Interpreter 解释器模式(行为型模式)

    Interpreter 解释器模式(行为型模式) 动机(Motivation) 在软件构建过程中,如果某一特定领域的问题比较复杂,类似的模式不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变 ...

随机推荐

  1. jquery版时钟(css3实现)

    做时钟的主要原因是因为喜欢,觉得它好看(本人对特效有点爱不释手……).做的时候感觉工程量会有点大,做着做着发现实现起来其实并不难,只要理清思绪,其实还蛮简单的(我制作东西喜欢整体方向制定好,然后边做边 ...

  2. homework160809207刘兆轩

    # include <stdio.h> int main() { float a,b,c,m,n,l,k,j,i; printf("请输入三个数:\n"); scanf ...

  3. BZOJ 2438: [中山市选2011]杀人游戏

    Description 给你一个有向图,求至少询问多少次能够得到全部点的信息. Sol Tarjan + 强连通分量缩点 + 判断. 先缩点,如果我们知道了强连通分量里的任意一个点,我们就可以知道这些 ...

  4. 补上题代码 hdu1520

    #include<iostream> #include<cmath> #include<algorithm> #include<vector> #inc ...

  5. java去除字符串中的空格、回车、换行符、制表符

    import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author chzeze * 2016-11-07 */ ...

  6. flask路由和视图和cookie

    什么是路由 """ 客户端(例如web浏览器)把请求发送给Web服务器,Web服务器再把请求发送给Flask程序实例. 程序实例需要知道对每个URL请求运行那些代码,所以 ...

  7. 11.8---维护x的秩(CC150)

    思路:比较easy.就是借助hashset让他有序然后就能够比较节省时间了. 答案: public static int[] getRankOfNumber(int[] a, int n){ int[ ...

  8. 转:jQuery弹出二级菜单

    <html> <head> <meta http-equiv="content-type" content="text/html; char ...

  9. Unity3d 扩展自定义类Inspector

    public class MyClass : MonoBehaviour { public int A; // Use this for initialization void Start () { ...

  10. pc/app 项目/功能设计

    2015-08-11 15:29:59 首先, 提供服务的整个系统包含哪几个设备 用户->[PC浏览器|APP|APP浏览器]->web服务器->[PHP/JAVA组件]->[ ...