最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Java設(shè)計模式之備忘錄模式的使用

 更新時間:2016年02月17日 11:34:42   作者:卡奴達摩  
這篇文章主要介紹了Java設(shè)計模式之備忘錄模式的使用,備忘錄模式中的發(fā)起者和管需要的朋友可以參考下

定義與結(jié)構(gòu)    

備忘錄(Memento)模式又稱標記(Token)模式。GOF給備忘錄模式的定義為:在不破壞封裝性的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài)。這樣以后就可將該對象恢復(fù)到原先保存的狀態(tài)。

  在講命令模式的時候,我們曾經(jīng)提到利用中間的命令角色可以實現(xiàn)undo、redo的功能。從定義可以看出備忘錄模式是專門來存放對象歷史狀態(tài)的,這對于很好的實現(xiàn)undo、redo功能有很大的幫助。所以在命令模式中undo、redo功能可以配合備忘錄模式來實現(xiàn)。

  其實單就實現(xiàn)保存一個對象在某一時刻的狀態(tài)的功能,還是很簡單的——將對象中要保存的屬性放到一個專門管理備份的對象中,需要的時候則調(diào)用約定好的方法將備份的屬性放回到原來的對象中去。但是你要好好看看為了能讓你的備份對象訪問到原對象中的屬性,是否意味著你就要全部公開或者包內(nèi)公開對象原本私有的屬性呢?如果你的做法已經(jīng)破壞了封裝,那么就要考慮重構(gòu)一下了。

  備忘錄模式只是GOF對“恢復(fù)對象某時的原有狀態(tài)”這一問題提出的通用方案。因此在如何保持封裝性上——由于受到語言特性等因素的影響,備忘錄模式并沒有詳細描述,只是基于C++闡述了思路。


  1) 備忘錄(Memento)角色:備忘錄角色存儲“備忘發(fā)起角色”的內(nèi)部狀態(tài)?!皞渫l(fā)起角色”根據(jù)需要決定備忘錄角色存儲“備忘發(fā)起角色”的哪些內(nèi)部狀態(tài)。為了防止“備忘發(fā)起角色”以外的其他對象訪問備忘錄。備忘錄實際上有兩個接口,“備忘錄管理者角色”只能看到備忘錄提供的窄接口——對于備忘錄角色中存放的屬性是不可見的?!皞渫l(fā)起角色”則能夠看到一個寬接口——能夠得到自己放入備忘錄角色中屬性。

  2) 備忘發(fā)起(Originator)角色:“備忘發(fā)起角色”創(chuàng)建一個備忘錄,用以記錄當(dāng)前時刻它的內(nèi)部狀態(tài)。在需要時使用備忘錄恢復(fù)內(nèi)部狀態(tài)。

  3) 備忘錄管理者(Caretaker)角色:負責(zé)保存好備忘錄。不能對備忘錄的內(nèi)容進行操作或檢查。

  備忘錄模式的類圖真是再簡單不過了:

2016217112919585.jpg (518×47)

通用代碼實現(xiàn)

class Originator { 
  private String state = ""; 
   
  public String getState() { 
    return state; 
  } 
  public void setState(String state) { 
    this.state = state; 
  } 
  public Memento createMemento(){ 
    return new Memento(this.state); 
  } 
  public void restoreMemento(Memento memento){ 
    this.setState(memento.getState()); 
  } 
} 
 
class Memento { 
  private String state = ""; 
  public Memento(String state){ 
    this.state = state; 
  } 
  public String getState() { 
    return state; 
  } 
  public void setState(String state) { 
    this.state = state; 
  } 
} 
class Caretaker { 
  private Memento memento; 
  public Memento getMemento(){ 
    return memento; 
  } 
  public void setMemento(Memento memento){ 
    this.memento = memento; 
  } 
} 
public class Client { 
  public static void main(String[] args){ 
    Originator originator = new Originator(); 
    originator.setState("狀態(tài)1"); 
    System.out.println("初始狀態(tài):"+originator.getState()); 
    Caretaker caretaker = new Caretaker(); 
    caretaker.setMemento(originator.createMemento()); 
    originator.setState("狀態(tài)2"); 
    System.out.println("改變后狀態(tài):"+originator.getState()); 
    originator.restoreMemento(caretaker.getMemento()); 
    System.out.println("恢復(fù)后狀態(tài):"+originator.getState()); 
  } 
} 

        代碼演示了一個單狀態(tài)單備份的例子,邏輯非常簡單:Originator類中的state變量需要備份,以便在需要的時候恢復(fù);Memento類中,也有一個state變量,用來存儲Originator類中state變量的臨時狀態(tài);而Caretaker類就是用來管理備忘錄類的,用來向備忘錄對象中寫入狀態(tài)或者取回狀態(tài)。

多狀態(tài)多備份備忘錄
       通用代碼演示的例子中,Originator類只有一個state變量需要備份,而通常情況下,發(fā)起人角色通常是一個javaBean,對象中需要備份的變量不止一個,需要備份的狀態(tài)也不止一個,這就是多狀態(tài)多備份備忘錄。實現(xiàn)備忘錄的方法很多,備忘錄模式有很多變形和處理方式,像通用代碼那樣的方式一般不會用到,多數(shù)情況下的備忘錄模式,是多狀態(tài)多備份的。其實實現(xiàn)多狀態(tài)多備份也很簡單,最常用的方法是,我們在Memento中增加一個Map容器來存儲所有的狀態(tài),在Caretaker類中同樣使用一個Map容器才存儲所有的備份。下面我們給出一個多狀態(tài)多備份的例子:

class Originator { 
  private String state1 = ""; 
  private String state2 = ""; 
  private String state3 = ""; 
 
  public String getState1() { 
    return state1; 
  } 
  public void setState1(String state1) { 
    this.state1 = state1; 
  } 
  public String getState2() { 
    return state2; 
  } 
  public void setState2(String state2) { 
    this.state2 = state2; 
  } 
  public String getState3() { 
    return state3; 
  } 
  public void setState3(String state3) { 
    this.state3 = state3; 
  } 
  public Memento createMemento(){ 
    return new Memento(BeanUtils.backupProp(this)); 
  } 
   
  public void restoreMemento(Memento memento){ 
    BeanUtils.restoreProp(this, memento.getStateMap()); 
  } 
  public String toString(){ 
    return "state1="+state1+"state2="+state2+"state3="+state3; 
  } 
} 
class Memento { 
  private Map<String, Object> stateMap; 
   
  public Memento(Map<String, Object> map){ 
    this.stateMap = map; 
  } 
 
  public Map<String, Object> getStateMap() { 
    return stateMap; 
  } 
 
  public void setStateMap(Map<String, Object> stateMap) { 
    this.stateMap = stateMap; 
  } 
} 
class BeanUtils { 
  public static Map<String, Object> backupProp(Object bean){ 
    Map<String, Object> result = new HashMap<String, Object>(); 
    try{ 
      BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); 
      PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); 
      for(PropertyDescriptor des: descriptors){ 
        String fieldName = des.getName(); 
        Method getter = des.getReadMethod(); 
        Object fieldValue = getter.invoke(bean, new Object[]{}); 
        if(!fieldName.equalsIgnoreCase("class")){ 
          result.put(fieldName, fieldValue); 
        } 
      } 
       
    }catch(Exception e){ 
      e.printStackTrace(); 
    } 
    return result; 
  } 
   
  public static void restoreProp(Object bean, Map<String, Object> propMap){ 
    try { 
      BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); 
      PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); 
      for(PropertyDescriptor des: descriptors){ 
        String fieldName = des.getName(); 
        if(propMap.containsKey(fieldName)){ 
          Method setter = des.getWriteMethod(); 
          setter.invoke(bean, new Object[]{propMap.get(fieldName)}); 
        } 
      } 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
} 
class Caretaker { 
  private Map<String, Memento> memMap = new HashMap<String, Memento>(); 
  public Memento getMemento(String index){ 
    return memMap.get(index); 
  } 
   
  public void setMemento(String index, Memento memento){ 
    this.memMap.put(index, memento); 
  } 
} 
class Client { 
  public static void main(String[] args){ 
    Originator ori = new Originator(); 
    Caretaker caretaker = new Caretaker(); 
    ori.setState1("中國"); 
    ori.setState2("強盛"); 
    ori.setState3("繁榮"); 
    System.out.println("===初始化狀態(tài)===\n"+ori); 
     
    caretaker.setMemento("001",ori.createMemento()); 
    ori.setState1("軟件"); 
    ori.setState2("架構(gòu)"); 
    ori.setState3("優(yōu)秀"); 
    System.out.println("===修改后狀態(tài)===\n"+ori); 
     
    ori.restoreMemento(caretaker.getMemento("001")); 
    System.out.println("===恢復(fù)后狀態(tài)===\n"+ori); 
  } 
} 

備忘錄模式的優(yōu)缺點和適用場景
備忘錄模式的優(yōu)點有:
當(dāng)發(fā)起人角色中的狀態(tài)改變時,有可能這是個錯誤的改變,我們使用備忘錄模式就可以把這個錯誤的改變還原。
備份的狀態(tài)是保存在發(fā)起人角色之外的,這樣,發(fā)起人角色就不需要對各個備份的狀態(tài)進行管理。
備忘錄模式的缺點:
在實際應(yīng)用中,備忘錄模式都是多狀態(tài)和多備份的,發(fā)起人角色的狀態(tài)需要存儲到備忘錄對象中,對資源的消耗是比較嚴重的。
如果有需要提供回滾操作的需求,使用備忘錄模式非常適合,比如jdbc的事務(wù)操作,文本編輯器的Ctrl+Z恢復(fù)等。

相關(guān)文章

  • 永中文檔在線轉(zhuǎn)換服務(wù)Swagger調(diào)用說明

    永中文檔在線轉(zhuǎn)換服務(wù)Swagger調(diào)用說明

    這篇文章主要為大家介紹了永中文檔在線轉(zhuǎn)換服務(wù)Swagger調(diào)用說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Java運行Jar包內(nèi)存配置的操作

    Java運行Jar包內(nèi)存配置的操作

    這篇文章主要介紹了Java運行Jar包內(nèi)存配置的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • java實現(xiàn)微信支付(服務(wù)端)

    java實現(xiàn)微信支付(服務(wù)端)

    這篇文章主要介紹了java實現(xiàn)微信支付,針對服務(wù)端進行代碼編寫,感興趣的小伙伴們可以參考一下
    2015-12-12
  • 詳解Spring 基于 Aspect 注解的增強實現(xiàn)

    詳解Spring 基于 Aspect 注解的增強實現(xiàn)

    本篇文章主要介紹了詳解Spring 基于 Aspect 注解的增強實現(xiàn),非常具有實用價值,需要的朋友可以參考下
    2017-04-04
  • springboot實現(xiàn)防重復(fù)提交和防重復(fù)點擊的示例

    springboot實現(xiàn)防重復(fù)提交和防重復(fù)點擊的示例

    這篇文章主要介紹了springboot實現(xiàn)防重復(fù)提交和防重復(fù)點擊的示例,幫助大家更好的理解和學(xué)習(xí)springboot框架,感興趣的朋友可以了解下
    2020-09-09
  • Java調(diào)用python的方法(jython)

    Java調(diào)用python的方法(jython)

    這篇文章主要介紹了Java調(diào)用python的方法(jython),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • 淺析 ArrayList 和 LinkedList 有什么區(qū)別

    淺析 ArrayList 和 LinkedList 有什么區(qū)別

    ArrayList 和 LinkedList 有什么區(qū)別,是面試官非常喜歡問的一個問題。今天通過本文給大家詳細介紹下,感興趣的朋友跟隨小編一起看看吧
    2020-10-10
  • 使用Maven進行依賴排除的詳細步驟

    使用Maven進行依賴排除的詳細步驟

    在Maven中,依賴排除是一種常見的技術(shù),用于從項目的依賴中排除特定的傳遞性依賴,這通常用于解決依賴沖突或避免引入不需要的庫,以下是如何在Maven中使用依賴排除的詳細步驟,包括代碼示例,需要的朋友可以參考下
    2024-11-11
  • Java中常用的日期類圖文詳解

    Java中常用的日期類圖文詳解

    Java提供了Date類來處理日期、時間(此處的Date是指java.util包下的Date類,而不是java.sql包下的Date類),Date對象既包含日期,也包含時間,下面這篇文章主要給大家介紹了關(guān)于Java中常用的日期類的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • 詳解Java中LinkedHashMap

    詳解Java中LinkedHashMap

    本文主要介紹了Java中LinkedHashMap的相關(guān)知識,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-05-05

最新評論

紫阳县| 上饶县| 庆云县| 获嘉县| 日喀则市| 左贡县| 大埔县| 平凉市| 萍乡市| 会同县| 商洛市| 茂名市| 赤城县| 团风县| 云龙县| 周口市| 庆安县| 敦煌市| 崇义县| 河西区| 东山县| 柞水县| 江孜县| 济阳县| 紫金县| 洛浦县| 商洛市| 姚安县| 屏山县| 东兰县| 旬邑县| 渭源县| 宜城市| 芒康县| 社会| 满城县| 莱阳市| 安达市| 汶上县| 景谷| 辽阳县|