概述

先从面向对象的三大特征之一封装说起。面向对象的封装简单点说就是把状态(数据)和行为(操作这些数据的方法)放到一起,构成一个单元,通常叫做类。一个对象的行为是事先确定好的(静态)一些脚本,如果对象的状态相同,对象看起来就是一样的。所以当我们需要把一个对象的某一时刻保存起来,那么只需要保存它在那个时刻的状态;相反需要恢复对象到某一时刻时,只需恢复它在那个时刻的状态。这就是备忘录模式的原理。

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

上面是GOF对备忘录模式的意图描述,非常清楚,内部状态保存到外部,再从外部恢复对象。

实现时我们通常把需要保存起来的状态封装为一个对象,用这个对象作为一个信息的载体,保存或恢复。出于避免外界对这些信息进行窜改,有必要对这个信息载体进行一个抽象,让外界只知道这是一个信息载体,而不知道具体承载了什么内容(窄接口);而内部可以获得载体所载有的全部信息(宽接口)。

备忘录模式常用来实现“撤销/重做”。

结构

备忘录模式的类图:

模式的参与者只有三个,相对简单。

1、作为对象状态信息载体的备忘录对象——IMemento、Memento,其中IMemento为对外的窄接口,而具体实现Memento则是对内的宽接口;

2、需要保存和恢复状态的对象,成为原发器——Originator;

3、管理和持有备忘录的备忘录负责人——Caretaker;

示例

有一个电子书阅读器,人们可以用它来阅读电子文档。阅读器提供了书签的功能,用户可以保存书签,也可以从使用一个书签使阅读器变为建立书签时的状态。我们简化一下,假设阅读器可以从书名和书的页码两个参数确定自身状态。

上面的需求很符合备忘录模式,书签可以看作备忘录对象,阅读器可以看作原发器,而隐含的书签管理结构可以作为负责人。

1、定义备忘录接口IBookmark(对外窄接口)。

 1:  using System;
 2:   
 3:  namespace DesignPatterns.Memento
 4:  {
 5:      /// <summary>
 6:      /// 书签接口(对外的窄接口)
 7:      /// </summary>
 8:      public interface IBookmark
 9:      { }
10:  }
11:   

2、阅读器类Reader,同时以私有内部类的形式实现具体的备忘录Bookmark(对内宽接口)。

 1:  using System;
 2:   
 3:  namespace DesignPatterns.Memento
 4:  {
 5:      /// <summary>
 6:      /// 阅读器
 7:      /// </summary>
 8:      public class Reader
 9:      {
10:          public Reader(string bookName, int pageNumber)
11:          {
12:              this.bookName = bookName;
13:              this.pageNumber = pageNumber;
14:          }
15:   
16:          //书名
17:          private string bookName;
18:   
19:          //页码
20:          private int pageNumber;
21:   
22:          //获得一个书签
23:          public IBookmark GetBookmark()
24:          {
25:              Console.WriteLine("建立书签:《" + this.bookName + "》第" + pageNumber + "页");
26:              return new Bookmark(this.bookName, this.pageNumber);
27:          }
28:   
29:          //从书签恢复
30:          public void Restore(IBookmark bookMark)
31:          {
32:              Bookmark bk = (Bookmark)bookMark;
33:              this.bookName = bk.BookName;
34:              this.pageNumber = bk.PageNumber;
35:              Console.WriteLine("恢复书签:《" + this.bookName + "》第" + pageNumber + "页");
36:          }
37:   
38:          //阅读
39:          public void Read()
40:          {
41:              Console.WriteLine("阅读:《" + this.bookName + "》第" + pageNumber + "页"); //阅读
42:              pageNumber++; //翻页
43:          }
44:   
45:          /// <summary>
46:          /// 书签实现(用内部类的方式实现对外的保密,或者说对内的宽接口)
47:          /// </summary>
48:          private class Bookmark : IBookmark
49:          {
50:              public Bookmark(string bookName, int pageNumber)
51:              {
52:                  this.BookName = bookName;
53:                  this.PageNumber = pageNumber;
54:              }
55:   
56:              /// <summary>
57:              /// 书名
58:              /// </summary>
59:              public string BookName { get; set; }
60:   
61:              /// <summary>
62:              /// 页码
63:              /// </summary>
64:              public int PageNumber { get; set; }
65:          }
66:      }
67:  }
68:   

3、书签管理器BookmarkCaretaker。

 1:  using System;
 2:  using System.Collections.Generic;
 3:   
 4:  namespace DesignPatterns.Memento
 5:  {
 6:      /// <summary>
 7:      /// 书签管理器
 8:      /// </summary>
 9:      public class BookmarkCaretaker
10:      {
11:          public BookmarkCaretaker()
12:          {
13:              this.bookmarks = new Dictionary<int, IBookmark>();
14:          }
15:   
16:          private Dictionary<int, IBookmark> bookmarks;
17:   
18:          public void AddBookmark(int key, IBookmark bookmark)
19:          {
20:              this.bookmarks.Add(key, bookmark);
21:          }
22:   
23:          public void RemoveBookmark(int key)
24:          {
25:              this.bookmarks.Remove(key);
26:          }
27:   
28:          public IBookmark GetBookmark(int key)
29:          {
30:              return bookmarks[key];
31:          }
32:      }
33:  }
34:   

4、测试客户端代码。

 1:  using System;
 2:   
 3:  namespace DesignPatterns.Memento
 4:  {
 5:      class Program
 6:      {
 7:          static void Main(string[] args)
 8:          {
 9:              BookmarkCaretaker caretaker = new BookmarkCaretaker();
10:              Reader reader = new Reader("设计模式", 1);
11:              reader.Read();
12:              reader.Read();
13:              reader.Read();
14:   
15:              caretaker.AddBookmark(1, reader.GetBookmark());
16:              reader.Read();
17:              reader.Read();
18:   
19:              caretaker.AddBookmark(2, reader.GetBookmark());
20:              reader.Read();
21:   
22:              reader.Restore(caretaker.GetBookmark(1));
23:              reader.Read();
24:   
25:              Console.WriteLine("按任意键结束...");
26:              Console.ReadKey();
27:          }
28:      }
29:  }
30:   

5、运行,查看结果。

转载于:https://www.cnblogs.com/zdy_bit/archive/2012/09/14/2684568.html

温故知新(8)——备忘录模式相关推荐

  1. 设计模式之备忘录模式(Memento)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  2. java备忘录模式应用场景_图解Java设计模式之备忘录模式

    图解Java设计模式之备忘录模式 游戏角色状态恢复问题 游戏角色有攻击力和防御力,在大战Boss前保存自身的状态(攻击力和防御力),当大战Boss后攻击力和防御力下降,从备忘录对象恢复到大战前的状态. ...

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

    2019独角兽企业重金招聘Python工程师标准>>> 本章讲讲第三类和第四类. 备忘录模式(Memento) 主要目的是保存一个对象的某个状态,以便在适当的时候恢复对象,个人觉得叫 ...

  4. 《JAVA与模式》之备忘录模式

    备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式. 备忘录对象是一个用来存储另外一个对象内部状态的快照的对象.备忘录模式的用意是在不破坏封装的条件下,将一 ...

  5. Python设计模式-备忘录模式

    Python设计模式-备忘录模式 代码基于3.5.2,代码如下; #coding:utf-8 #备忘录模式 import randomclass gameCharacter():vitality = ...

  6. 【设计模式】备忘录模式

    备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象.备忘录模式属于行为型模式. 介绍 意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存 ...

  7. 备忘录模式(Memento)的原版与简化版实现

    备忘录模式(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 适用场景: 1.保存一个对象在某一个时刻的(部分) ...

  8. Java设计模式(备忘录模式-解释器模式-状态模式-策略模式-职责链模式)

    Java设计模式Ⅶ 1.备忘录模式 1.1 备忘录模式概述 1.2 代码理解 2.解释器模式 2.1 解释器模式概述 3.状态模式 3.1 状态模式概述 3.2 代码理解 4.策略模式 4.1 策略模 ...

  9. php在线备忘录,备忘录模式(Memento)

    namespace DesignPatterns\Behavioral\Memento\Tests; use DesignPatterns\Behavioral\Memento\Caretaker; ...

最新文章

  1. java泛型的实现和原理_java 泛型实现原理
  2. 互联网技术的主要组成
  3. 黄忠---忠心不二主
  4. 2.2.2 进程调度的 时机 切换与过程 调度方式
  5. [Python爬虫] 在Windows下安装PhantomJS和CasperJS及入门介绍(上)
  6. Scala教程之:可扩展的scala
  7. HDU 3094 树上删边 NIM变形
  8. 实战02_SSM整合ActiveMQ支持多种类型消息
  9. 如何使用Python的Flask和Google App Engine构建网络应用
  10. nnFormer (Not-aNother transFORMER): 基于交叉Transformer结构的3D医疗影像分割网络
  11. 关于eclipse环境启动不成功的问题解决方法
  12. web前端开发规范总结
  13. 纯个人整理!分享珍藏很久的《手把手AI项目》合集手册(附链接)
  14. IOUtils工具类简介及应用
  15. 拼多多带货视频是什么?拼多多带货视频如何上传
  16. JavaScript中document的四种方法
  17. 约翰 霍普克罗夫特计算机科学中心,北京大学
  18. 魅族16支持html吗,魅族16功能有哪些
  19. 轮循与连接-- 细雪之舞
  20. 【Linux】进程管理之kill、killall、pkill

热门文章

  1. Spring @scope注解
  2. 【SSL】weblogic 12c自带默认证书库密码
  3. json传输二进制的方案(python版)
  4. html 属于mvvm框架,mvvm模式和mvc的区别是什么?
  5. java esp_在我的ESP游戏方法中非法开始表达
  6. android10 内部存储,Android的内部存储和外部存储
  7. android java 延时函数,如何在Android中设置文本之间的延迟
  8. Centos 卸载mysql
  9. 两次深度debug经历,希望大家不要踩坑
  10. 华为欧拉操作系统发布,将推出自研编程语言打通鸿蒙和欧拉