温故知新(8)——备忘录模式
概述
先從面向對象的三大特征之一封裝說起。面向對象的封裝簡單點說就是把狀態(數據)和行為(操作這些數據的方法)放到一起,構成一個單元,通常叫做類。一個對象的行為是事先確定好的(靜態)一些腳本,如果對象的狀態相同,對象看起來就是一樣的。所以當我們需要把一個對象的某一時刻保存起來,那么只需要保存它在那個時刻的狀態;相反需要恢復對象到某一時刻時,只需恢復它在那個時刻的狀態。這就是備忘錄模式的原理。
在不破壞封裝性的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這個狀態。這樣以后就可將該對象恢復到原先保存的狀態。
上面是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)——备忘录模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: wordpress博客留言自动填写
- 下一篇: Android分享中, 过滤指定的应用,