fbpx
维基百科

備忘錄模式

備忘錄模式是一种软件设计模式,可以將一個物件內部私有的狀態公開。可以使用此模式的一個例子是將物件回復到其先前的状态(撤消變更),還有的例子是版本控制,以及自定义序列化。

備忘錄模式主要由三個角色來實現:發起者、管理員和備忘錄。發起者是具有內部狀態的角色。管理員可以對發起起者做一些操作,尤其是希望能够撤消變更的操作。竹管理員首先向發起者索要一件備忘錄。然后它执行此操作(或操作序列)。為了可以回滚到操作之前的状态,它将備忘錄返回给发起者。備忘錄本身是一个不透明的物件(管理員不能或不應更改此物件)。使用此模式時,應注意發起者是否可能更改其他物件或資源——備忘錄模式是對單一物件進行操作。

備忘錄模式的經典範例有伪随机数生成器(PRNG)(每個消費者(管理員)在初始化偽隨機數生成器(發起者)時,若使用相同的種子值(備忘錄),可以產生相同的亂數序列),此外,還有有限状态机及其狀態。

概述 编辑

備忘錄設計模式是著名的《設計模式:可復用物件導向軟體的基礎》所收錄的二十三個之一。此書描述了如何解決常見的設計問题,以設計出彈性且異重用的物件導向软件(亦即更容易實現、更改、测试、维护和重用的物件)。備忘錄模式是由 Noah Thompson、David Espiritu 和 Drew Clinkenbeard 博士为惠普早期产品创建的。

備忘錄設計模式可以解決什麼問題? 编辑

  • 物件的内部狀態須要保存在外部,以便之後可將物件回復到此狀態。
  • 不違反物件的封裝性。

問题在於,一個良好設計的物件會被封装起来,其表示(資料結構)是隐藏在物件内部,且無法從外部存取。

備忘錄設計模式描述了什么解决方案? 编辑

让一个物件(發起者)本身负责

  • 将其内部状态保存到(備忘錄)物件,並且
  • 从(備忘錄)物件回復到以前的狀態。

只有產生此備忘錄的發起者可以存取它。

客户端(管理員)可以向發起者請求備忘錄(以保存發起者的内部状态)并将備忘錄传递回發起者(以恢复到先前的状态)。

这使得外部能够在不破壞其封装的情况下,保存和回復發起者的内部狀態。

請參考下面的 UML 類別圖和序列圖。

结构 编辑

UML 類別圖和序列圖 编辑

 
備忘錄設計模式的 UML 類別圖和序列圖。 [1]

在上面的UML类图中, Caretaker 類別指向向 Originator 類別,用于保存( createMemento() )和恢复( restore(memento) )始发者的内部状态。Originator 類別實現了(1) createMemento() ,藉由創建並返回 Memento 物件,其記錄了發起者當前内部状态,(2) restore(memento),藉由將 Memento 物件傳入,以回復狀態。

UML序列图显示了运行时交動:(1) 保存发起者的内部状态: Caretaker对象在Originator对象上调用createMemento() ,创建一个Memento对象,保存其当前的内部状态 ( setState() ),并将Memento返回给Caretaker 。(2) 恢复Originator的内部状态: CaretakerOriginator对象调用restore(memento) ,并指定存储应恢复状态的Memento对象。 OriginatorMemento获取状态 ( getState() ) 以设置自己的状态。

Java 範例 编辑

以下的 Java 程序说明了備忘錄模式的“撤消變更”用法。

import java.util.List; import java.util.ArrayList; class Originator {  private String state;  // 這個類別可以包含其它不用存在 State 中的備忘錄  public void set(String state) {  this.state = state;  System.out.println("Originator: Setting state to " + state);  }    public Memento saveToMemento() {  System.out.println("Originator: Saving to Memento.");  return new Memento(this.state);  }    public void restoreFromMemento(Memento memento) {  this.state = memento.getSavedState();  System.out.println("Originator: State after restoring from Memento: " + state);  }    public static class Memento {  private final String state;  public Memento(String stateToSave) {  state = stateToSave;  }    // accessible by outer class only  private String getSavedState() {  return state;  }  } }   class Caretaker {  public static void main(String[] args) {  List<Originator.Memento> savedStates = new ArrayList<Originator.Memento>();    Originator originator = new Originator();  originator.set("State1");  originator.set("State2");  savedStates.add(originator.saveToMemento());  originator.set("State3");  // 我們可以要求多個備忘錄,並選擇要回復到那個狀態。  savedStates.add(originator.saveToMemento());  originator.set("State4");    originator.restoreFromMemento(savedStates.get(1));   } } 

输出是:

Originator: Setting state to State1 Originator: Setting state to State2 Originator: Saving to Memento. Originator: Setting state to State3 Originator: Saving to Memento. Originator: Setting state to State4 Originator: State after restoring from Memento: State3 

本示例使用 String 作为状态,它是 Java 中的不可变物件。在现实生活中,状态几乎总是一个可变物件,在这种情况下,必须创建状态的副本。

必须指出的是,所展示的实现有一个缺点:它声明了一个内部类。如果備忘錄可以适用于多个发起者,則會更好。

实现Memento 还有其他三种主要方式:

  1. 序列化。
  2. 在同一个包中声明的類別。
  3. 还可以通过代理来访问该物件,代理可以实现对物件的任何保存/恢复操作。

C# 示例 编辑

備忘錄模式允许人們在不違反封装的情况下捕获物件的内部状态,以便以后可以根據需求來撤消變更/回復變更。從这里可以看出,備忘錄物件实际上用于恢复物件中所做的更改。

class Memento {  private readonly string savedState;  private Memento(string stateToSave)  {  savedState = stateToSave;  }  public class Originator  {  private string state;  // The class could also contain additional data that is not part of the  // state saved in the memento.  public void Set(string state)  {  Console.WriteLine("Originator: Setting state to " + state);  this.state = state;  }  public Memento SaveToMemento()  {  Console.WriteLine("Originator: Saving to Memento.");  return new Memento(state);  }  public void RestoreFromMemento(Memento memento)  {  state = memento.savedState;  Console.WriteLine("Originator: State after restoring from Memento: " + state);  }  } } class Caretaker {  static void Main(string[] args)  {  var savedStates = new List<Memento>();  var originator = new Memento.Originator();  originator.Set("State1");  originator.Set("State2");  savedStates.Add(originator.SaveToMemento());  originator.Set("State3");  // We can request multiple mementos, and choose which one to roll back to.  savedStates.Add(originator.SaveToMemento());  originator.Set("State4");  originator.RestoreFromMemento(savedStates[1]);  } } 

Python 範例 编辑

""" 備忘錄模式範例 """ class Originator: _state = "" def set(self, state: str) -> None: print(f"Originator: Setting state to {state}") self._state = state def save_to_memento(self) -> "Memento": return self.Memento(self._state) def restore_from_memento(self, m: "Memento") -> None: self._state = m.get_saved_state() print(f"Originator: State after restoring from Memento: {self._state}") class Memento: def __init__(self, state):  self._state = state def get_saved_state(self):  return self._state saved_states = [] originator = Originator() originator.set("State1") originator.set("State2") saved_states.append(originator.save_to_memento()) originator.set("State3") saved_states.append(originator.save_to_memento()) originator.set("State4") originator.restore_from_memento(saved_states[1]) 

JavaScript 範列 编辑

// The Memento pattern is used to save and restore the state of an object. // A memento is a snapshot of an object's state. var Memento = {// Namespace: Memento  savedState : null, // The saved state of the object.  save : function(state) { // Save the state of an object.  this.savedState = state;  },  restore : function() { // Restore the state of an object.  return this.savedState;  } }; // The Originator is the object that creates the memento. // defines a method for saving the state inside a memento. var Originator = {// Namespace: Originator  state : null, // The state to be stored  // Creates a new originator with an initial state of null  createMemento : function() {   return {   state : this.state // The state is copied to the memento.  };  },  setMemento : function(memento) { // Sets the state of the originator from a memento  this.state = memento.state;  }  }; // The Caretaker stores mementos of the objects and // provides operations to retrieve them. var Caretaker = {// Namespace: Caretaker  mementos : [], // The mementos of the objects.  addMemento : function(memento) { // Add a memento to the collection.  this.mementos.push(memento);  },  getMemento : function(index) { // Get a memento from the collection.  return this.mementos[index];  }  }; var action_step = "Foo"; // The action to be executed/the object state to be stored. var action_step_2 = "Bar"; // The action to be executed/the object state to be stored. // 設置初始值 Originator.state = action_step; Caretaker.addMemento(Originator.createMemento());// save the state to the history console.log("Initial State: " + Originator.state); // Foo // 改變初始值 Originator.state = action_step_2; Caretaker.addMemento(Originator.createMemento()); // save the state to the history console.log("State After Change: " + Originator.state); // Bar // 回復到第一個狀態——撤消變更 Originator.setMemento(Caretaker.getMemento(0)); console.log("State After Undo: " + Originator.state); // Foo // 回復到第二個狀態——重做變更 Originator.setMemento(Caretaker.getMemento(1)); console.log("State After Redo: " + Originator.state); // Bar 

参考 编辑

  1. ^ The Memento design pattern - Structure and Collaboration. w3sDesign.com. [2017-08-12]. 

備忘錄模式, 是一种软件设计模式, 可以將一個物件內部私有的狀態公開, 可以使用此模式的一個例子是將物件回復到其先前的状态, 撤消變更, 還有的例子是版本控制, 以及自定义序列化, 主要由三個角色來實現, 發起者, 管理員和備忘錄, 發起者是具有內部狀態的角色, 管理員可以對發起起者做一些操作, 尤其是希望能够撤消變更的操作, 竹管理員首先向發起者索要一件備忘錄, 然后它执行此操作, 或操作序列, 為了可以回滚到操作之前的状态, 它将備忘錄返回给发起者, 備忘錄本身是一个不透明的物件, 管理員不能或不應更改此物件,. 備忘錄模式是一种软件设计模式 可以將一個物件內部私有的狀態公開 可以使用此模式的一個例子是將物件回復到其先前的状态 撤消變更 還有的例子是版本控制 以及自定义序列化 備忘錄模式主要由三個角色來實現 發起者 管理員和備忘錄 發起者是具有內部狀態的角色 管理員可以對發起起者做一些操作 尤其是希望能够撤消變更的操作 竹管理員首先向發起者索要一件備忘錄 然后它执行此操作 或操作序列 為了可以回滚到操作之前的状态 它将備忘錄返回给发起者 備忘錄本身是一个不透明的物件 管理員不能或不應更改此物件 使用此模式時 應注意發起者是否可能更改其他物件或資源 備忘錄模式是對單一物件進行操作 備忘錄模式的經典範例有伪随机数生成器 PRNG 每個消費者 管理員 在初始化偽隨機數生成器 發起者 時 若使用相同的種子值 備忘錄 可以產生相同的亂數序列 此外 還有有限状态机及其狀態 目录 1 概述 1 1 備忘錄設計模式可以解決什麼問題 1 2 備忘錄設計模式描述了什么解决方案 2 结构 2 1 UML 類別圖和序列圖 3 Java 範例 4 C 示例 5 Python 範例 6 JavaScript 範列 7 参考概述 编辑備忘錄設計模式是著名的 設計模式 可復用物件導向軟體的基礎 所收錄的二十三個之一 此書描述了如何解決常見的設計問题 以設計出彈性且異重用的物件導向软件 亦即更容易實現 更改 测试 维护和重用的物件 備忘錄模式是由 Noah Thompson David Espiritu 和 Drew Clinkenbeard 博士为惠普早期产品创建的 備忘錄設計模式可以解決什麼問題 编辑 物件的内部狀態須要保存在外部 以便之後可將物件回復到此狀態 不違反物件的封裝性 問题在於 一個良好設計的物件會被封装起来 其表示 資料結構 是隐藏在物件内部 且無法從外部存取 備忘錄設計模式描述了什么解决方案 编辑 让一个物件 發起者 本身负责 将其内部状态保存到 備忘錄 物件 並且 从 備忘錄 物件回復到以前的狀態 只有產生此備忘錄的發起者可以存取它 客户端 管理員 可以向發起者請求備忘錄 以保存發起者的内部状态 并将備忘錄传递回發起者 以恢复到先前的状态 这使得外部能够在不破壞其封装的情况下 保存和回復發起者的内部狀態 請參考下面的 UML 類別圖和序列圖 结构 编辑UML 類別圖和序列圖 编辑 nbsp 備忘錄設計模式的 UML 類別圖和序列圖 1 在上面的UML类图中 Caretaker 類別指向向 Originator 類別 用于保存 createMemento 和恢复 restore memento 始发者的内部状态 Originator 類別實現了 1 createMemento 藉由創建並返回 Memento 物件 其記錄了發起者當前内部状态 2 restore memento 藉由將 Memento 物件傳入 以回復狀態 UML序列图显示了运行时交動 1 保存发起者的内部状态 Caretaker对象在Originator对象上调用createMemento 创建一个Memento对象 保存其当前的内部状态 setState 并将Memento返回给Caretaker 2 恢复Originator的内部状态 Caretaker对Originator对象调用restore memento 并指定存储应恢复状态的Memento对象 Originator从Memento获取状态 getState 以设置自己的状态 Java 範例 编辑以下的 Java 程序说明了備忘錄模式的 撤消變更 用法 import java util List import java util ArrayList class Originator private String state 這個類別可以包含其它不用存在 State 中的備忘錄 public void set String state this state state System out println Originator Setting state to state public Memento saveToMemento System out println Originator Saving to Memento return new Memento this state public void restoreFromMemento Memento memento this state memento getSavedState System out println Originator State after restoring from Memento state public static class Memento private final String state public Memento String stateToSave state stateToSave accessible by outer class only private String getSavedState return state class Caretaker public static void main String args List lt Originator Memento gt savedStates new ArrayList lt Originator Memento gt Originator originator new Originator originator set State1 originator set State2 savedStates add originator saveToMemento originator set State3 我們可以要求多個備忘錄 並選擇要回復到那個狀態 savedStates add originator saveToMemento originator set State4 originator restoreFromMemento savedStates get 1 输出是 Originator Setting state to State1 Originator Setting state to State2 Originator Saving to Memento Originator Setting state to State3 Originator Saving to Memento Originator Setting state to State4 Originator State after restoring from Memento State3 本示例使用 String 作为状态 它是 Java 中的不可变物件 在现实生活中 状态几乎总是一个可变物件 在这种情况下 必须创建状态的副本 必须指出的是 所展示的实现有一个缺点 它声明了一个内部类 如果備忘錄可以适用于多个发起者 則會更好 实现Memento 还有其他三种主要方式 序列化 在同一个包中声明的類別 还可以通过代理来访问该物件 代理可以实现对物件的任何保存 恢复操作 C 示例 编辑備忘錄模式允许人們在不違反封装的情况下捕获物件的内部状态 以便以后可以根據需求來撤消變更 回復變更 從这里可以看出 備忘錄物件实际上用于恢复物件中所做的更改 class Memento private readonly string savedState private Memento string stateToSave savedState stateToSave public class Originator private string state The class could also contain additional data that is not part of the state saved in the memento public void Set string state Console WriteLine Originator Setting state to state this state state public Memento SaveToMemento Console WriteLine Originator Saving to Memento return new Memento state public void RestoreFromMemento Memento memento state memento savedState Console WriteLine Originator State after restoring from Memento state class Caretaker static void Main string args var savedStates new List lt Memento gt var originator new Memento Originator originator Set State1 originator Set State2 savedStates Add originator SaveToMemento originator Set State3 We can request multiple mementos and choose which one to roll back to savedStates Add originator SaveToMemento originator Set State4 originator RestoreFromMemento savedStates 1 Python 範例 编辑 備忘錄模式範例 class Originator state def set self state str gt None print f Originator Setting state to state self state state def save to memento self gt Memento return self Memento self state def restore from memento self m Memento gt None self state m get saved state print f Originator State after restoring from Memento self state class Memento def init self state self state state def get saved state self return self state saved states originator Originator originator set State1 originator set State2 saved states append originator save to memento originator set State3 saved states append originator save to memento originator set State4 originator restore from memento saved states 1 JavaScript 範列 编辑 The Memento pattern is used to save and restore the state of an object A memento is a snapshot of an object s state var Memento Namespace Memento savedState null The saved state of the object save function state Save the state of an object this savedState state restore function Restore the state of an object return this savedState The Originator is the object that creates the memento defines a method for saving the state inside a memento var Originator Namespace Originator state null The state to be stored Creates a new originator with an initial state of null createMemento function return state this state The state is copied to the memento setMemento function memento Sets the state of the originator from a memento this state memento state The Caretaker stores mementos of the objects and provides operations to retrieve them var Caretaker Namespace Caretaker mementos The mementos of the objects addMemento function memento Add a memento to the collection this mementos push memento getMemento function index Get a memento from the collection return this mementos index var action step Foo The action to be executed the object state to be stored var action step 2 Bar The action to be executed the object state to be stored 設置初始值 Originator state action step Caretaker addMemento Originator createMemento save the state to the history console log Initial State Originator state Foo 改變初始值 Originator state action step 2 Caretaker addMemento Originator createMemento save the state to the history console log State After Change Originator state Bar 回復到第一個狀態 撤消變更 Originator setMemento Caretaker getMemento 0 console log State After Undo Originator state Foo 回復到第二個狀態 重做變更 Originator setMemento Caretaker getMemento 1 console log State After Redo Originator state Bar参考 编辑 The Memento design pattern Structure and Collaboration w3sDesign com 2017 08 12 取自 https zh wikipedia org w index php title 備忘錄模式 amp oldid 79775671, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。