亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

備忘錄模式(Memento Pattern)

2019-11-18 12:15:59
字體:
來源:轉載
供稿:網友

  描述:
  
  對象的狀態可以定義為在特定的時間點對象的屬性值。備忘錄模式(Memento Pattern)應用于保存和跟蹤對象的狀態,以便于必要的時候可以把對象恢復到以前的狀態。它很像恢復操作。備忘錄模式(Memento Pattern)可以在不暴露對象的內部結構的情況下完成這樣的功能。需要獲取以前狀態的對象就是指發起者(Originator)。當客戶需要保存發起者的狀態時,客戶需要發起者的當前狀態。發起者存貯所有保持它狀態的屬性到一個獨立的對象,這個對象就是備忘錄(紀念、記憶)Memento,把備忘錄(Memento)對象返回給客戶。備忘錄(Memento)對象可以看作在給定的時間點包含另一個對象內部狀態的對象。備忘錄(Memento)對象必須向除了發起者以外的所有對象隱藏發起者變量的值。當發起者答應備忘錄(Memento)對象訪問它的內部狀態時,備忘錄(Memento)對象應該被設計為對其他對象采取訪問限制的對象。
  
  當客戶需要把發起者的狀態恢復到以前的狀態時,它只是簡單的把備忘錄(Memento)對象返回給發起者。發起者使用包含在備忘錄(Memento)對象中的狀態信息,恢復自己到備忘錄(Memento)對象中保存的狀態。
  
  例子:
  
  數據轉化(Data conversion)總是那些涉及到從遺留系統轉化到應用新技術的系統不可缺少的一部分。讓我們假定一個需要把客戶數據從文本文件移植到關系型數據庫中的類似應用程序。在將客戶數據發送給數據庫以前,要對客戶紀錄進行驗證。
  
  現實中,客戶紀錄需要包括很多屬性,但是為了簡單,讓我們假定每一個客戶紀錄只有三個屬性??first name、last name和credit card number。驗證過程也很簡單,只要last name不為空而且credit card number(信用卡號)僅有0-9的數字組成。當發現一個無效的客戶記錄時,驗證過程需要停止、提示用戶修正數據并重新開始。在這個時間點上,數據轉化(Data conversion)過程的狀態需要保存在一個備忘錄(Memento)對象內部。當用戶重新開始驗證過程時,數據裝化過程從保存在備忘錄(Memento)對象中的狀態開始,驗證過程從它停止的地方恢復,而不是從原數據起點重新開始。通常,備忘錄(Memento)對象既可以保存在內存中也可以保存在持久介質上。在這個應用中,當應用被打斷以后,狀態需要保存,而且當應用再次運行的時候需要恢復。因此,在這種情況下,不適于把備忘錄(Memento)對象保存在內存中,而是需要保存在持久介質上。
  
  不是直接把合法的客戶紀錄插入到關系數據庫中,應用程序而是生成一個由SQL插入語句組成的文本文件,執行這些SQL語句可以把數據插入到數據庫中。
  
  讓我們為這個驗證過程設計不同的組件。
  
  DataConverter(發起者)
  
  DataConverter類(圖32.1和Listing32.1)是數據轉化過程的實現。
  
 備忘錄模式(Memento Pattern)(圖一)
  Figure 32.1: DataConverter Class?The Originator
  

  Listing 32.1: DataConverter Class
  
  public class DataConverter {
  public static final String DATA_FILE = "Data.txt";
  public static final String OUTPUT_FILE = "SQL.txt";
  PRivate long ID = 0;
  public Memento createMemento() {
  return (new Memento(ID));
  }
  public void setMemento(Memento memento) {
  if (memento != null)
  ID = memento.getID();
  }
  public long getLastProcessedID() {
  return ID;
  }
  public void setLastProcessedID(long lastID) {
  ID = lastID;
  }
  public boolean process() {
  boolean sUCcess = true;
  String inputLine = "";
  long currID = 0;
  try {
  File inFile = new File(DATA_FILE);
  BufferedReader br = new BufferedReader(
  new InputStreamReader(
  new FileInputStream(inFile)));
  long lastID = getLastProcessedID();
  while ((inputLine = br.readLine()) != null) {
  StringTokenizer st =
  new StringTokenizer(inputLine, ",");
  String strID = st.nextToken();
  currID = new Long(strID).longValue();
  if (lastID < currID) {
  Customer c =
  new Customer(strID, st.nextToken(),
  st.nextToken(), st.nextToken());
  if (!(c.isValid())) {
  success = false;
  break;
  }
  ID = new Long(strID).longValue();
  FileUtil util = new FileUtil();
  util.writeToFile(OUTPUT_FILE, c.getSQL(),
  true, true);
  }
  }
  br.close();
  }//Try
  catch (Exception ex) {
  System.out.println(" An error has occurred " +
  ex.getMessage());
  System.exit(1);
  }
  if (success == false) {
  System.out.println("An error has occurred at ID=" +
  currID);
  System.out.println("Data Record=" + inputLine);
  return false;
  }
  return true;
  }
  class Memento implements java.io.Serializable {
  private long lastProcessedID;
  private Memento(long ID) {
  lastProcessedID = ID;
  }
  private long getID() {
  return lastProcessedID;
  }
  }//end of class
  }//end of class
  
  ID
  
  實例變量ID組成了DataConverter的狀態,它代表了最后一個被成功處理的客戶紀錄的客戶ID。
  
  Memento
  
  Memento定義為DataConverter的一個內部類,Memento將它的構造函數和其他方法定義為私有。
  
  在Java中,一個類可以訪問它內部類的私有成員。
  
  DataConverter可以訪問這些方法,但是其他的對象不可以訪問。因為,當應用結束的時候,DataConverter的狀態需要被保存。Memento對象需要被序列化(serialize)到一個文件中。因此,Memento類需要實現java.io.Serializable接口,以表明自己是一個可序列化(Serializable)的類。
  
  在JAVA中,一個序列化的類必須:
  
  使用transient 要害字明確指出不需要序列化的屬性。
  實現java.io.Serializable接口
  可以訪問它的第一個非序列化夫類的零參數的構造函數。
  
  process
  
  process方法讀取元數據文件,通過Customer helper類驗證客戶數據。對于每一個有效的客戶紀錄,相應的SQL插入語句被寫入到輸出文件中。當碰到無效客戶紀錄時,數據轉化過程停止。
  
  createMemento
  
  如方法名字,這個方法負責創建Memento對象,它把DataConverter對象的當前狀態保存到一個Memento實例內,并放回它。
  
  setMemento
  
  取出輸入的Memento對象的狀態信息,重新設置DataConverter的狀態到此狀態。
  
  DCClient (Client)
  
  客戶DCClient(Listing 32.2)首先初始化DataConverter,調用DataConverter實例的process方法開始數據轉化過程。假如process方法在處理原數據文件期間碰到無效的客戶數據,它會調用DataConverter實例的createMemento方法捕捉當前狀態。createMemento方法返回一個Memento對象。客戶DCClient使用MementoHandler對象負責序列化Memento實例到一個文件。
  
  Listing 32.2: DCClient Class
  
  public class DCClient {
  public static void main(String[] args) {
  MementoHandler objMementoHandler = new MementoHandler();
  DataConverter objConverter = new DataConverter();
  objConverter.setMemento(objMementoHandler.getMemento());
  if (!(objConverter.process())) {
  System.out.println("Description: Invalid data - " +
  "Process Stopped");
  System.out.println("Please correct the Data and " +
  "Run the application Again");
  objMementoHandler.setMemento(
  objConverter.createMemento());
  }
  }
  }
  
  一旦數據被校正,客戶DCClient就會再次運行。
  
  客戶DCClient調用MementoHandler 上的getMemento 方法請求它保存Memento對象。
  MementoHandler 從文件中反序列化以前的Memento對象,并把它放回給客戶。
  客戶把它作為DataConverter 的set-Memento方法的參數傳遞給DataConverter 。DataConverter使自己返回到保存在Memento對象中的狀態。從原來停止的地方恢復數據轉化過程。
  
  MementoHandler
  
  The MementoHandler (Listing 32.3) 包含了Memento 對象的一個引用??蛻鬌CClient把一個Memento的實例傳遞給它。
  
  Listing 32.3: MementoHandler Class
  
  public class MementoHandler {
  public static final String ID_FILE = "ID.txt";
  private DataConverter.Memento objMemento = null;
  public DataConverter.Memento getMemento() {
  ObjectInputStream objStream = null;
  FileUtil util = new FileUtil();
  if (util.isFileExists(ID_FILE)) {
  //read the object from the file
  try {
  objStream = new ObjectInputStream(
  new FileInputStream(new File(ID_FILE)));
  objMemento = (DataConverter.Memento)
  objStream.readObject();
  objStream.close();
  } catch (Exception e) {
  System.out.println("Error Reading Memento");
  System.exit(1);
  }
  //delete the old memento
  util.deleteFile(ID_FILE);
  }
  return objMemento;
  }
  public void setMemento(DataConverter.Memento memento) {
  ObjectOutputStream objStream = null;
  //write the object to the file
  try {
  objStream = new ObjectOutputStream(
  new FileOutputStream(new File(ID_FILE)));
  objStream.writeObject(memento);
  objStream.close();
  } catch (Exception e) {
  System.out.println("Error Writing Memento");
  System.exit(1);
  }
  }
  }//end of class
  
  如上面介紹的,任何時候數據轉化過程沒有驗證完全部的原數據文件,客戶要捕捉DataConverter的狀態到一個Memento中,并停止應用程序。為了使這個Memento在下次運行的時候有效,它必須被保存到持久介質上,這就涉及到了對象的序列化。假如在下次運行的時候,DataConverter要返回到它原來的狀態,這個Memento對象必須被重構,這又涉及到了對象的反序列化。這些細節由MementoHandler類來處理,使得所有客戶(DataConverter和Memento對象)免于處理這些細節。
  
  這樣也是的改變Memento的存儲方式變得很輕易。例如,Memento需要保存到數據庫中,而不是文件中時,只要修改MementoHandler就可以了,不需要修改任何客戶類的實現。
  
  圖32.2顯示了在數據轉化這個例子中,不同對象之間的關聯關系。
  
 備忘錄模式(Memento Pattern)(圖二)
  Figure 32.2: Data Conversion Application?Class Association
  

  Figure 32.3 shows the application message flow.
  
 備忘錄模式(Memento Pattern)(圖三)
  Figure 32.3: Application Message Flow
  

  例子2(自己找的)
  
  經常使用計算機的人恐怕對系統備份(Memento)不會生疏,當你的Windows系統運行正常時,對它進行備份,當系統運行有問題時,就可以調用備份快速的將系統恢復,這樣就可以大量節省重新裝系統的痛苦,非凡是當你缺少某一驅動,或在裝系統是出現一些怪問題時,猶為痛苦。我想有過這種經歷的人應該很了解吧,呵呵!
  
  好了,下面讓我們看看這個過程該如何實現吧:
  
  1、我們先定義Windows系統(WindowsSystem)類:
  
  public class WindowsSystem {
  private String state;
  public Memento createMemento() { //創建備份,保存當前狀態
  return new Memento(state);
  }
  public void restoreMemento(Memento memento){ //從備份中恢復系統
  this.state=memento.getState();
  }
  public String getState(){ //獲得狀態
  return this.state;
  }
  public void setState(String state){ //設置狀態
  this.state=state;
  System.out.println(當前系統處于+this.state);
  }
  }
  
  2、再定義備份(Memento)類:
  
  public class Memento {
  private String state;
  public Memento(String state) { //備份
  this.state=state;
  }
  public String getState(){ //獲得狀態
  return this.state;
  }
  public void setState(String state){ //設置狀態
  this.state=state;
  }
  }
  
  3、定義用戶(User)類:
  
  public class User {
  private Memento memento;
  public Memento retrieveMemento() { //恢復系統
  return this.memento;
  }
  public void saveMemento(Memento memento){ //保存系統
  this.memento=memento;
  }
  }
  
  4、編寫測試類:
  
  public class Test {
  public static void main(String args[]) {
  WindowsSystem WinXP = new WindowsSystem(); //Winxp系統
  User user = new User();  //某一用戶
  Winxp.setState(好的狀態);  //Winxp處于好的運行狀態
  user.saveMemento(Winxp.createMemento()); //用戶對系統進行備份,Winxp系統要產生備份文件
  Winxp.setState(壞的狀態);  //Winxp處于不好的運行狀態
  Winxp.restoreMemento(user.retrieveMemento());  //用戶發恢復命令,系統進行恢復
  System.out.println(當前系統處于+Winxp.getState());
  }
  }
  
  5、說明:
  
  A:定義:Memento對象是一個保存另外一個對象內部狀態拷貝的對象,這樣以后就可以將該對象恢復到原先保存的狀態。
  
  B:Memento模式的用意是在不破壞封裝的條件下,將一個對象的狀態捕捉住,并外部化,存儲起來,從而可以在將來合適的時候把這個對象還原到存儲起來的狀態。
  
  C:Memento模式所涉及的角色有三個,備忘錄角色、發起人角色和負責人角色。
  
  備忘錄角色的作用:
  
  (1)    將發起人對象的內部狀態存儲起來,備忘錄可以根據發起人對象的判定來決定存儲多少發起人對象的內部狀態。
  
 ?。?)    備忘錄可以保護其內容不被發起人對象之外的任何對象所讀取。
  
  發起人角色的作用:
  
  (1)    創建一個含有當前內部狀態的備忘錄對象。
  
  (2)    使用備忘錄對象存儲其內部狀態。
  
  負責人角色的作用:
  

  (1)    負責保存備忘錄對象。
  
  (2)    不檢查備忘錄對象的內容。
  
  D:在本例中,備份(Memento)類是備忘錄角色、Windows系統(WindowsSystem)類是發起人角色、用戶(User)類是負責人角色。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品爽黄69天堂a| 日韩欧美一区视频| 国产成人激情视频| 夜夜躁日日躁狠狠久久88av| 清纯唯美日韩制服另类| 欧美成人午夜视频| 欧美第一淫aaasss性| 欧洲亚洲女同hd| 亚洲成年人影院在线| 欧美一级淫片播放口| 欧美午夜精品久久久久久久| 欧美黄色www| 最新国产精品拍自在线播放| 黄色成人在线免费| 亚洲国产精品悠悠久久琪琪| 日韩电影中文字幕av| 久久久久亚洲精品国产| 日韩av电影在线播放| 精品亚洲男同gayvideo网站| 国模私拍视频一区| 91精品国产沙发| 成人精品久久av网站| 国产欧美日韩免费看aⅴ视频| 亚洲天天在线日亚洲洲精| 亚洲色图综合久久| 97色在线视频观看| 精品国产老师黑色丝袜高跟鞋| 中文字幕少妇一区二区三区| 日韩电影第一页| 国产精品久久久久久久久免费| 日韩av在线网址| 欧美中文字幕在线视频| 成人精品久久久| 亚洲免费电影一区| 亚洲va久久久噜噜噜久久天堂| 人人爽久久涩噜噜噜网站| 另类色图亚洲色图| 97视频网站入口| 国产精品美女无圣光视频| 亚洲精品动漫久久久久| 91香蕉亚洲精品| 亚洲xxx大片| 亚洲国产成人精品女人久久久| 精品久久久久久久久国产字幕| 欧美一级淫片aaaaaaa视频| 亚洲午夜未删减在线观看| 国产婷婷成人久久av免费高清| 成人欧美在线视频| 国产一区二区三区视频| 欧美性猛交xxxx乱大交| 国产精品久久久久久久7电影| 欧美日韩中文字幕日韩欧美| 久久影视三级福利片| 欧美激情在线狂野欧美精品| 亚洲成人精品视频| 欧美国产亚洲视频| 国产精品99久久久久久人| 国产精品第一区| 国产精品美乳一区二区免费| 国产精品一区=区| 在线观看精品国产视频| 久精品免费视频| 日韩乱码在线视频| 理论片在线不卡免费观看| 欧美激情视频在线| 亚洲自拍偷拍一区| 亚洲第一网站男人都懂| 91精品久久久久久| 亚洲成人教育av| 庆余年2免费日韩剧观看大牛| 日本久久中文字幕| 国产精品国模在线| 国产女同一区二区| 国产精品麻豆va在线播放| 青青a在线精品免费观看| 日韩中文字幕第一页| 亚洲欧美制服第一页| 亚洲电影免费观看| 国产精品91久久久| 国产一级揄自揄精品视频| 亚洲精品久久久久久久久久久久| 国产欧美精品va在线观看| 亚洲男人的天堂在线| 9.1国产丝袜在线观看| 韩国精品久久久999| 亚洲精品综合久久中文字幕| 亚洲一区www| 91在线观看免费高清完整版在线观看| 久久久久免费精品国产| 亚洲自拍偷拍第一页| 97人人爽人人喊人人模波多| 国产精品成人免费电影| 国产精品久久久久久久久| 91影视免费在线观看| 91大神在线播放精品| 黑人巨大精品欧美一区二区免费| 亚洲精品久久视频| www.亚洲天堂| 国产精品视频不卡| 久久99精品久久久久久青青91| 亚洲天堂2020| 91爱视频在线| 亚州av一区二区| 亚洲精品日韩丝袜精品| 亚洲第一在线视频| www.99久久热国产日韩欧美.com| 欧美国产一区二区三区| 中文字幕日韩av电影| 成人在线中文字幕| 国产精品欧美一区二区三区奶水| 裸体女人亚洲精品一区| 欧美小视频在线| 成人欧美一区二区三区黑人孕妇| 97久久精品视频| 国产日韩在线看| 日韩视频―中文字幕| 国产69久久精品成人看| 国产精品久久婷婷六月丁香| 久久这里只有精品99| 成人有码在线视频| 亚洲www视频| 国产精品高精视频免费| 中文字幕亚洲情99在线| 日韩欧美一区二区三区| 91国语精品自产拍在线观看性色| 人人澡人人澡人人看欧美| 亚洲精品视频播放| 91深夜福利视频| 亚洲自拍另类欧美丝袜| 亚洲黄在线观看| 91精品国产综合久久久久久蜜臀| 在线精品国产欧美| 久久久亚洲精选| 亚洲一区二区三区四区视频| 亚洲精品视频网上网址在线观看| 久久亚洲欧美日韩精品专区| 91精品国产91久久久久久吃药| 欧美极品在线播放| 成人免费自拍视频| 精品亚洲一区二区三区| 亚洲欧洲在线看| 岛国av一区二区在线在线观看| 久精品免费视频| 日韩精品免费视频| 亚洲欧美日韩国产精品| 亚洲欧美日韩国产中文专区| 欧美性猛交xxxx乱大交蜜桃| 国产91精品久久久| 91亚洲国产精品| 欧美国产第二页| 色噜噜狠狠色综合网图区| 亚洲字幕一区二区| 欧美日韩国产一区二区| 狠狠操狠狠色综合网| 欧美色videos| 精品国内自产拍在线观看| 曰本色欧美视频在线| 韩国精品美女www爽爽爽视频| 91社区国产高清| 国产精品视频26uuu| 日韩高清人体午夜| 伊人久久精品视频| 夜夜嗨av色综合久久久综合网| 国产精品视频一区二区高潮|