在软件的构建过程中,某些对象的状态在转换过程中,可能由于某种需要,要求程序能够回溯到对象之前某个点时的状态,如果使用一些公有接口来让其他对象得到对象的状态,便会暴露对象的细节实现。   
  如何实现对象状态的良好保存与恢复?但同时又不会因此而破坏对象本身的封装性。
  Memento 备忘录模式提供解决途径,它在不破坏封装性的前提下,捕获一个对象的内部状态,并在这个对象之外保存这个状态。这样就可以将对象恢复到原先保存的状态。《设计模式》— GOF
  Memento备忘录模式UML图如下:

主要角色:
  1、原发器角色Originator:它是我们关注的对象,我们需要保存和回溯的状态就是它的状态。我们需要在它内部创建备忘录对象并利用备忘录对象保存我们需要保存的状态值,同时它还需要提供一种手段来恢复我们以前保存的状态值.
  2、备忘录对象Memento:它用于在不破坏封装性的前提下,捕获一个Originator的内部状态,并在备忘录对象Memento中保存这个状态。(Caretaker:用于防止原发器以外的对象访问备忘录对象,保证备忘录对象的安全性)。
  下面我们用代码来示例,程序如下:

一、备忘录模式思路示例
   1、原发器角色Originator

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyMementoPattern
{
    //Memento模式适用于由原发器管理,却又必须存储在原发器之外的信息
    //定义原发器对象:Originator
    //有必要对自身内部状态进行保存,然后在某个点处又需要恢复内部状态的对象

class Originator
    {
        #region State属性
        private string _state;
        public string State
        {
            get { return _state; }
            set { 
                  _state = value;
                  Console.WriteLine("State={0}",_state);
                 }
        }
        #endregion

//在实现Memento模式中,要防止原发器Originator以外的对象访问备忘录对象,备忘录对象有两个接口,一个为原发器使用的宽接口,一个为其他对象使用的窄接口

#region 创建Memento类的方法(Memento类将用于保存Originator对象的State状态值)
        public Memento CreateMemento()
        {
            Console.WriteLine("创建Memento对象并保存状态到此对象中..");
            return (new Memento(_state)); //此处,在创建Memento对象时就保存了对象状态
          
        }
        #endregion

#region 利用上面Memento对象保存的状态值进行状态恢复操作
        public void SetMemento(Memento memnto)
        {
            Console.WriteLine("恢复对象状态..");
            State = memnto.State; 
        }
        #endregion
    }
}

2、备忘录对象Memento

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyMementoPattern
{
    class Memento
    {
        //定义备忘录对象Memento类,它专门用于保存Originator类对象的状态信息
        //也即:在不破坏封装性的前提下,捕获一个Originator的内部状态,并在这个对象之外保存这个状态。
        //而这个状态值就保存在Memento类中
        private string _state;
        public string State
        {
            get { return _state; }
        }

#region 构造函数
        public Memento(string state)
        {
            this._state = state;
        }
        #endregion
    }
}

3、Caretaker

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyMementoPattern
{

//定义CareTaker类
    //此类的作用是保证Mmento类的安全性
    class CareTaker
    {
        private Memento _memento;
        public Memento Memento
        {
            get { return _memento; }
            set { _memento = value; }
        }
    }
}

4、客户端应用

Code
            #region 基本思路示例
             Console.WriteLine("-------------备忘录模式基本思路示例---------------");

Originator o = new Originator();
            o.State = "On";  //设置Originator类对象状态

CareTaker c = new CareTaker();
            c.Memento = o.CreateMemento();

Console.WriteLine("设置状态新值.");
            o.State = "Off";

o.SetMemento(c.Memento);

Console.ReadKey();
            #endregion

二、在客户对象上使用备忘录模式
   1、原发器角色Originator:ClientsOriginator

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyMementoPattern
{
    class ClientsOriginator
    {
        #region 姓名属性
        private string _name;

public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                Console.WriteLine("姓名:  " + _name);
            }
        }
        #endregion

#region 电话属性
        private string _phone;
        public string Phone
        {
            get { return _phone; }
            set
            {   _phone = value;
                Console.WriteLine("电话: " + _phone);
            }
        }
        #endregion

#region 住址属性
        private string _address;
        public string Address
        {
            get { return _address; }
            set
            {
                _address = value;
                Console.WriteLine("住址: " + _address);
            }
        }
        #endregion

public ClientMemento SaveMemento()
        {
            Console.WriteLine("\n 保存客户状态 \n");
            return (new ClientMemento(_name,_phone,_address));
        }

public void RestoreMemento(ClientMemento memento)
        {
            Console.WriteLine("\n 恢复客户状态值\n");
            this.Name = memento.Name;
            this.Phone = memento.Phone;
            this.Address = memento.Address;
        }

}
}

2、备忘录对象Memento:ClientsMemento

Code
using System;
using
 System.Collections.Generic;
using
 System.Linq;
using
 System.Text;

namespace MyMementoPattern
{
    class
 ClientMemento
    {
        #region 姓名属性

        private string _name;

public string Name
        {
            get { return
 _name; }
            set {_name =
 value; }
        }
        #endregion

        #region 电话属性
        private string _phone;
        public string
 Phone
        {
            get { return
 _phone; }
            set { _phone =
 value; }
        }
        #endregion

        #region 住址属性
        private string _address;
        public string
 Address
        {
            get { return
 _address; }
            set { _address =
 value; }
        }
        #endregion

        public ClientMemento(string name,string phone, string address)
        {
            this._name =
 name;
            this._phone =
 phone;
            this._address =
 address;
            
        }
    }
}

3、Caretaker:ClientMemory

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyMementoPattern
{
    class ClientMemory
    {
        private ClientMemento memento;
        public ClientMemento Memento
        {
            get { return memento; }
            set { memento = value; }
        }
    }
}

4、客户端应用

Code
           #region 客户状态示例
            Console.WriteLine("-------------在客户对象上使用备忘录模式---------------");
            ClientsOriginator co = new
 ClientsOriginator();

co.Name = "王军";
            co.Phone = "86150338"
;
            co.Address = "北京"
;

ClientMemory cm = new ClientMemory();
            cm.Memento =
 co.SaveMemento();

Console.WriteLine("\n 修改客户状态 \n");
            co.Name = "王小军"
;
            co.Phone = "99999999"
;
            co.Address = "深圳"
;

co.RestoreMemento(cm.Memento);
            Console.ReadKey();
            #endregion

运行效果如下:
                        
 总结:

备忘录存储原发器(Originator)对象的内部状态,在需要时恢复原发器状态。Memento模式适用于由原发器管理,却又必须存储在原发器之外的信息
  在实现Memento模式中,要防止原发器以外的对象方位备忘录对象,备忘录对象有两个接口,一个为原发器使用的宽接口,一个为其他对象使用的窄接口。在上面的例子中Originator对于Memento看到是宽接口,即SetState方法,而用户端看到的是窄接口,即Memento的构造函数和Creatememento、SetMemento方法。
  在实现Memento模式时,要考虑拷贝对象状态的效率问题,如果对象开销比较大,可以采用某种增量式改变来跟进Memnto模式

前往:设计模式学习笔记清单

转载于:https://www.cnblogs.com/wsdj-ITtech/archive/2009/10/14/1582994.html

设计模式学习笔记--Memento 备忘录模式相关推荐

  1. 设计模式学习笔记:备忘录模式(Memento)

    文章目录 一.备忘录模式简介 二.适应场景 三.示例演示 四.测试示例 拥有乐观的心态很重要,它能让工作和生活更加美好. 一.备忘录模式简介 备忘录模式是设计模式中行为型模式的一种.备忘录模式用于保存 ...

  2. 设计模式学习笔记——解释器(Interpreter)模式

    设计模式学习笔记--解释器(Interpreter)模式 @(设计模式)[设计模式, 解释器模式, Interpreter] 设计模式学习笔记解释器Interpreter模式 基本介绍 解释器案例 类 ...

  3. 设计模式学习笔记——命令(Command)模式

    设计模式学习笔记--命令(Command)模式 @(设计模式)[设计模式, 命令模式, command] 设计模式学习笔记命令Command模式 基本介绍 命令案例 类图 实现代码 Command接口 ...

  4. 设计模式学习笔记——代理(Proxy)模式

    设计模式学习笔记--代理(Proxy)模式 @(设计模式)[设计模式, 代理模式, proxy] 设计模式学习笔记代理Proxy模式 基本介绍 代理案例 类图 实现代码 Printable接口 Pri ...

  5. 设计模式学习笔记——状态(State)模式框架

    设计模式学习笔记--状态(State)模式框架 @(设计模式)[设计模式, 状态模式, State] 设计模式学习笔记状态State模式框架 基本介绍 状态案例 类图 实现代码 State接口 Day ...

  6. 设计模式学习笔记——观察者(Observer)模式

    设计模式学习笔记--观察者(Observer)模式 @(设计模式)[设计模式, 观察者模式, Observer] 设计模式学习笔记观察者Observer模式 基本介绍 观察者案例 类图 实现代码 Ob ...

  7. 设计模式学习笔记——外观(Facade)模式

    设计模式学习笔记--外观(Facade)模式 @(设计模式)[设计模式, 外观模式, facade] 设计模式学习笔记外观Facade模式 基本介绍 外观案例 类图 实现代码 Database类 ma ...

  8. 设计模式学习笔记——访问者(Visitor)模式

    设计模式学习笔记--访问者(Visitor)模式 @(设计模式)[设计模式, 访问者模式, visitor] 设计模式学习笔记访问者Visitor模式 基本介绍 访问者案例 类图 实现代码 Visit ...

  9. 设计模式学习笔记——装饰(Decorator)模式

    设计模式学习笔记--装饰(Decorator)模式 @(设计模式)[设计模式, 装饰模式, decorator] 设计模式学习笔记装饰Decorator模式 基本介绍 装饰案例 类图 实现代码 Dis ...

最新文章

  1. VC6.0连接数据库,并把大量数据从ACCess转移到SQL sever2008 的问题(亲测可用)
  2. 【C++】const讲解
  3. boost::search相关的测试程序
  4. 病的不轻?教你 2 招,拯救拖延症!
  5. python数据库优化_python | Mysql性能优化一
  6. NetBeans 6.9 发布后选版 1 已经可用
  7. Dubbo(一) -- 初体验
  8. python iot_使用EduBlocks,适用于Linux的i3窗口管理器,必读新闻通讯,CI / CD,敏捷,IoT等进行Python编程
  9. Linux内核网络协议栈:udp数据包发送(源码解读)
  10. 如何学习Python进行数据分析
  11. 华为ICT大赛2016模拟题
  12. 详细版【机器学习概述】(邱锡鹏)
  13. 苹果产品信息查询_除了让你买买买,苹果官网还隐藏着这些超实用网页工具
  14. 智能手机成瘾者的大脑功能和结构的改变
  15. 关于Bmob后端云的使用
  16. 带有源代码的2020年20种最佳HTML5游戏模板
  17. 极路由4增强版编译aria2-1.34
  18. c语言阿拉伯数字转大写,c++阿拉伯数字转化为中文大写
  19. 计算机科学研究进展,理论计算研究获进展
  20. android 格式工厂,格式工厂app下载-格式工厂app安卓版下载[辅助工具]-华军软件园...

热门文章

  1. altium 网口差分走线长度_差分信号的优缺点及布线要求
  2. html字体颜色选择插件,css3改变选择文本背景颜色
  3. 比特币支付接口php,比特币支付php类
  4. mysql数据完整性约束包括_MYSQL回顾(完整性约束相关)
  5. 2台电脑一根网线传文件_用1根网线直连2台电脑,能干嘛?
  6. springboot完成进度条_Springboot从0开始第一周
  7. centos 7mysql加tomcat_CentOS 7环境搭建(JDK、Tomcat、Mysql)
  8. 如何区分两列中不同数据_如何区分原装数据线和山寨数据线
  9. java静态初始化块无法直接调用,关于JAVA静态初始化块,初始化块,构造器调用顺序的有关问题...
  10. linux扩容后显示管理,linux之lvm管理及扩容