Head First设计模式之备忘录模式
生活随笔
收集整理的這篇文章主要介紹了
Head First设计模式之备忘录模式
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、定義
不破壞封裝性的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這個狀態。這樣就可以將該對象恢復到原先保存的狀態
二、結構
備忘錄模式中主要有三類角色:
- 發起人角色:記錄當前時刻的內部狀態,負責創建和恢復備忘錄數據。
- 備忘錄角色:負責存儲發起人對象的內部狀態,在進行恢復時提供給發起人需要的狀態。
- 管理者角色:負責保存備忘錄對象,但是不能對備忘錄對象的內容進行操作或檢查。
三、適用場景
1、需要保存/恢復數據的相關狀態場景。
2、提供一個可回滾的操作。
四、優缺點
優點:?
1、給用戶提供了一種可以恢復狀態的機制,可以使用戶能夠比較方便地回到某個歷史的狀態。
2、實現了信息的封裝,使得用戶不需要關心狀態的保存細節。
缺點:
消耗資源。
1、如果類的成員變量過多,勢必會占用比較大的資源,而且每一次保存都會消耗一定的內存。
2、由于備份的信息是由發起人自己提供的,所以管理者無法預知備份的信息的大小,存在一定的未知風險。
?
五、實現
下面以備份手機通訊錄為例子來實現了備忘錄模式,具體的實現代碼如下所示:
單次備份
// 聯系人public class ContactPerson{public string Name { get; set; }public string MobileNum { get; set; }}// 發起人public class MobileOwner{// 發起人需要保存的內部狀態public List<ContactPerson> ContactPersons { get; set; }public MobileOwner(List<ContactPerson> persons){ContactPersons = persons;}// 創建備忘錄,將當期要保存的聯系人列表導入到備忘錄中 public ContactMemento CreateMemento(){// 這里也應該傳遞深拷貝,new List方式傳遞的是淺拷貝,// 因為ContactPerson類中都是string類型,所以這里new list方式對ContactPerson對象執行了深拷貝// 如果ContactPerson包括非string的引用類型就會有問題,所以這里也應該用序列化傳遞深拷貝return new ContactMemento(new List<ContactPerson>(this.ContactPersons));}// 將備忘錄中的數據備份導入到聯系人列表中public void RestoreMemento(ContactMemento memento){// 下面這種方式是錯誤的,因為這樣傳遞的是引用,// 則刪除一次可以恢復,但恢復之后再刪除的話就恢復不了.// 所以應該傳遞contactPersonBack的深拷貝,深拷貝可以使用序列化來完成this.ContactPersons = memento.contactPersonBack;}public void Show(){Console.WriteLine("聯系人列表中有{0}個人,他們是:", ContactPersons.Count);foreach (ContactPerson p in ContactPersons){Console.WriteLine("姓名: {0} 號碼為: {1}", p.Name, p.MobileNum);}}}// 備忘錄public class ContactMemento{// 保存發起人的內部狀態public List<ContactPerson> contactPersonBack;public ContactMemento(List<ContactPerson> persons){contactPersonBack = persons;}}// 管理角色public class Caretaker{public ContactMemento ContactM { get; set; }}class Program{static void Main(string[] args){List<ContactPerson> persons = new List<ContactPerson>(){new ContactPerson() { Name= "Learning Hard", MobileNum = "123445"},new ContactPerson() { Name = "Tony", MobileNum = "234565"},new ContactPerson() { Name = "Jock", MobileNum = "231455"}};MobileOwner mobileOwner = new MobileOwner(persons);mobileOwner.Show();// 創建備忘錄并保存備忘錄對象Caretaker caretaker = new Caretaker();caretaker.ContactM = mobileOwner.CreateMemento();// 更改發起人聯系人列表Console.WriteLine("----移除最后一個聯系人--------");mobileOwner.ContactPersons.RemoveAt(2);mobileOwner.Show();// 恢復到原始狀態Console.WriteLine("-------恢復聯系人列表------");mobileOwner.RestoreMemento(caretaker.ContactM);mobileOwner.Show();Console.Read();}}多次備份
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks;namespace DesignPatterns.Mememto {// 聯系人public class ContactPerson{public string Name { get; set; }public string MobileNum { get; set; }}// 發起人public class MobileOwner{public List<ContactPerson> ContactPersons { get; set; }public MobileOwner(List<ContactPerson> persons){ContactPersons = persons;}// 創建備忘錄,將當期要保存的聯系人列表導入到備忘錄中 public ContactMemento CreateMemento(){// 這里也應該傳遞深拷貝,new List方式傳遞的是淺拷貝,// 因為ContactPerson類中都是string類型,所以這里new list方式對ContactPerson對象執行了深拷貝// 如果ContactPerson包括非string的引用類型就會有問題,所以這里也應該用序列化傳遞深拷貝return new ContactMemento(new List<ContactPerson>(this.ContactPersons));}// 將備忘錄中的數據備份導入到聯系人列表中public void RestoreMemento(ContactMemento memento){if (memento != null){// 下面這種方式是錯誤的,因為這樣傳遞的是引用,// 則刪除一次可以恢復,但恢復之后再刪除的話就恢復不了.// 所以應該傳遞contactPersonBack的深拷貝,深拷貝可以使用序列化來完成this.ContactPersons = memento.ContactPersonBack;}}public void Show(){Console.WriteLine("聯系人列表中有{0}個人,他們是:", ContactPersons.Count);foreach (ContactPerson p in ContactPersons){Console.WriteLine("姓名: {0} 號碼為: {1}", p.Name, p.MobileNum);}}}// 備忘錄public class ContactMemento{public List<ContactPerson> ContactPersonBack { get; set; }public ContactMemento(List<ContactPerson> persons){ContactPersonBack = persons;}}// 管理角色public class Caretaker{// 使用多個備忘錄來存儲多個備份點public Dictionary<string, ContactMemento> ContactMementoDic { get; set; }public Caretaker(){ContactMementoDic = new Dictionary<string, ContactMemento>();}}class Program{static void Main(string[] args){List<ContactPerson> persons = new List<ContactPerson>(){new ContactPerson() { Name= "Learning Hard", MobileNum = "123445"},new ContactPerson() { Name = "Tony", MobileNum = "234565"},new ContactPerson() { Name = "Jock", MobileNum = "231455"}};MobileOwner mobileOwner = new MobileOwner(persons);mobileOwner.Show();// 創建備忘錄并保存備忘錄對象Caretaker caretaker = new Caretaker();caretaker.ContactMementoDic.Add(DateTime.Now.ToString(), mobileOwner.CreateMemento());// 更改發起人聯系人列表Console.WriteLine("----移除最后一個聯系人--------");mobileOwner.ContactPersons.RemoveAt(2);mobileOwner.Show();// 創建第二個備份Thread.Sleep(1000);caretaker.ContactMementoDic.Add(DateTime.Now.ToString(), mobileOwner.CreateMemento());// 恢復到原始狀態Console.WriteLine("-------恢復聯系人列表,請從以下列表選擇恢復的日期------");var keyCollection = caretaker.ContactMementoDic.Keys;foreach (string k in keyCollection){Console.WriteLine("Key = {0}", k);}while (true){Console.Write("請輸入數字,按窗口的關閉鍵退出:");int index = -1;try{index = Int32.Parse(Console.ReadLine());}catch{Console.WriteLine("輸入的格式錯誤");continue;}ContactMemento contactMentor = null;if (index < keyCollection.Count && caretaker.ContactMementoDic.TryGetValue(keyCollection.ElementAt(index), out contactMentor)){mobileOwner.RestoreMemento(contactMentor);mobileOwner.Show();}else{Console.WriteLine("輸入的索引大于集合長度!");}}}} }?
?
參考
http://www.cnblogs.com/JsonShare/p/7283972.html
http://www.runoob.com/design-pattern/memento-pattern.html
http://www.cnblogs.com/zhili/p/MementoPattern.html
?
歡迎閱讀本系列文章:Head First設計模式之目錄?
?
轉載于:https://www.cnblogs.com/xcsn/p/7498695.html
總結
以上是生活随笔為你收集整理的Head First设计模式之备忘录模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAVA中常用的逻辑运算符_Java中的
- 下一篇: python pyqt eric_科学网