自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

設(shè)計(jì)模式系列—備忘錄模式

開(kāi)發(fā) 前端
本篇和大家一起來(lái)學(xué)習(xí)備忘錄模式相關(guān)內(nèi)容。

 模式定義

在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài),以便以后當(dāng)需要時(shí)能將該對(duì)象恢復(fù)到原先保存的狀態(tài)。該模式又叫快照模式。

模版實(shí)現(xiàn)如下:

  1. package com.niuh.designpattern.memento.v1; 
  2.  
  3. /** 
  4.  * <p> 
  5.  * 備忘錄模式 
  6.  * </p> 
  7.  */ 
  8. public class MementoPattern { 
  9.     public static void main(String[] args) { 
  10.         Originator or = new Originator(); 
  11.         Caretaker cr = new Caretaker(); 
  12.         or.setState("S0"); 
  13.         System.out.println("初始狀態(tài):" + or.getState()); 
  14.         cr.setMemento(or.createMemento()); //保存狀態(tài)       
  15.         or.setState("S1"); 
  16.         System.out.println("新的狀態(tài):" + or.getState()); 
  17.         or.restoreMemento(cr.getMemento()); //恢復(fù)狀態(tài) 
  18.         System.out.println("恢復(fù)狀態(tài):" + or.getState()); 
  19.     } 
  20.  
  21. //備忘錄 
  22. class Memento { 
  23.     private String state; 
  24.  
  25.     public Memento(String state) { 
  26.         this.state = state; 
  27.     } 
  28.  
  29.     public void setState(String state) { 
  30.         this.state = state; 
  31.     } 
  32.  
  33.     public String getState() { 
  34.         return state; 
  35.     } 
  36.  
  37. //發(fā)起人 
  38. class Originator { 
  39.     private String state; 
  40.  
  41.     public void setState(String state) { 
  42.         this.state = state; 
  43.     } 
  44.  
  45.     public String getState() { 
  46.         return state; 
  47.     } 
  48.  
  49.     public Memento createMemento() { 
  50.         return new Memento(state); 
  51.     } 
  52.  
  53.     public void restoreMemento(Memento m) { 
  54.         this.setState(m.getState()); 
  55.     } 
  56.  
  57. //管理者 
  58. class Caretaker { 
  59.     private Memento memento; 
  60.  
  61.     public void setMemento(Memento m) { 
  62.         memento = m; 
  63.     } 
  64.  
  65.     public Memento getMemento() { 
  66.         return memento; 
  67.     } 

輸出結(jié)果如下:

  1. 初始狀態(tài):S0 
  2. 新的狀態(tài):S1 
  3. 恢復(fù)狀態(tài):S0 

解決的問(wèn)題

備忘錄模式能記錄一個(gè)對(duì)象的內(nèi)部狀態(tài),當(dāng)用戶后悔時(shí)能撤銷(xiāo)當(dāng)前操作,使數(shù)據(jù)恢復(fù)到它原先的狀態(tài)。

每個(gè)人都有犯錯(cuò)誤的時(shí)候,都希望有種“后悔藥”能彌補(bǔ)自己的過(guò)失,讓自己重新開(kāi)始,但現(xiàn)實(shí)是殘酷的。在計(jì)算機(jī)應(yīng)用中,客戶同樣會(huì)常常犯錯(cuò)誤,能否提供“后悔藥”給他們呢?當(dāng)然是可以的,而且是有必要的。這個(gè)功能由“備忘錄模式”來(lái)實(shí)現(xiàn)。

模式組成

 

備忘錄模式的核心是設(shè)計(jì)備忘錄類以及用于管理備忘錄的管理者類。

實(shí)例說(shuō)明

實(shí)例概況

 

以游戲存檔為例,看一下如何用備忘錄模式實(shí)現(xiàn)

使用步驟

 

步驟1:定義備忘錄角色,用于存儲(chǔ)角色狀態(tài)。

  1. class RoleStateMemento { 
  2.  
  3.     private int vit;    //生命力 
  4.     private int atk;    //攻擊力 
  5.     private int def;    //防御力 
  6.  
  7.     public RoleStateMemento(int vit, int atk, int def) { 
  8.         this.vit = vit; 
  9.         this.atk = atk; 
  10.         this.def = def; 
  11.     } 
  12.  
  13.     public int getVit() { 
  14.         return vit; 
  15.     } 
  16.  
  17.     public void setVit(int vit) { 
  18.         this.vit = vit; 
  19.     } 
  20.  
  21.     public int getAtk() { 
  22.         return atk; 
  23.     } 
  24.  
  25.     public void setAtk(int atk) { 
  26.         this.atk = atk; 
  27.     } 
  28.  
  29.     public int getDef() { 
  30.         return def; 
  31.     } 
  32.  
  33.     public void setDef(int def) { 
  34.         this.def = def; 
  35.     } 

步驟2:定義發(fā)起人角色(當(dāng)前游戲角色),記錄當(dāng)前游戲角色的生命力、攻擊力、防御力。通過(guò)saveState()方法來(lái)保存當(dāng)前狀態(tài),通過(guò)recoveryState()方法來(lái)恢復(fù)角色狀態(tài)。

  1. class GameRole { 
  2.  
  3.     private int vit;    //生命力 
  4.     private int atk;    //攻擊力 
  5.     private int def;    //防御力 
  6.  
  7.     public int getVit() { 
  8.         return vit; 
  9.     } 
  10.  
  11.     public void setVit(int vit) { 
  12.         this.vit = vit; 
  13.     } 
  14.  
  15.     public int getAtk() { 
  16.         return atk; 
  17.     } 
  18.  
  19.     public void setAtk(int atk) { 
  20.         this.atk = atk; 
  21.     } 
  22.  
  23.     public int getDef() { 
  24.         return def; 
  25.     } 
  26.  
  27.     public void setDef(int def) { 
  28.         this.def = def; 
  29.     } 
  30.  
  31.     //狀態(tài)顯示 
  32.     public void stateDisplay() { 
  33.         System.out.println("角色當(dāng)前狀態(tài):"); 
  34.         System.out.println("體力:" + this.vit); 
  35.         System.out.println("攻擊力:" + this.atk); 
  36.         System.out.println("防御力: " + this.def); 
  37.         System.out.println("-----------------"); 
  38.     } 
  39.  
  40.     //獲得初始狀態(tài) 
  41.     public void getInitState() { 
  42.         this.vit = 100; 
  43.         this.atk = 100; 
  44.         this.def = 100; 
  45.     } 
  46.  
  47.     //戰(zhàn)斗后 
  48.     public void fight() { 
  49.         this.vit = 0; 
  50.         this.atk = 0; 
  51.         this.def = 0; 
  52.     } 
  53.  
  54.     //保存角色狀態(tài) 
  55.     public RoleStateMemento saveState() { 
  56.         return (new RoleStateMemento(vit, atk, def)); 
  57.     } 
  58.  
  59.     //恢復(fù)角色狀態(tài) 
  60.     public void recoveryState(RoleStateMemento memento) { 
  61.         this.vit = memento.getVit(); 
  62.         this.atk = memento.getAtk(); 
  63.         this.def = memento.getDef(); 
  64.     } 

步驟3:定義管理者角色,角色狀態(tài)管理者

  1. class RoleStateCaretaker { 
  2.  
  3.     private RoleStateMemento memento; 
  4.  
  5.     public RoleStateMemento getMemento() { 
  6.         return memento; 
  7.     } 
  8.  
  9.     public void setMemento(RoleStateMemento memento) { 
  10.         this.memento = memento; 
  11.     } 

步驟4:測(cè)試輸出

  1. public class MementoPattern { 
  2.  
  3.     // 邏輯大致為打boss前存檔,打boss失敗了 
  4.     public static void main(String[] args) { 
  5.         //打boss前 
  6.         GameRole gameRole = new GameRole(); 
  7.         gameRole.getInitState(); 
  8.         gameRole.stateDisplay(); 
  9.  
  10.         //保存進(jìn)度 
  11.         RoleStateCaretaker caretaker = new RoleStateCaretaker(); 
  12.         caretaker.setMemento(gameRole.saveState()); 
  13.  
  14.         //打boss失敗 
  15.         gameRole.fight(); 
  16.         gameRole.stateDisplay(); 
  17.  
  18.         //恢復(fù)狀態(tài) 
  19.         gameRole.recoveryState(caretaker.getMemento()); 
  20.         gameRole.stateDisplay(); 
  21.     } 

輸出結(jié)果

  1. 角色當(dāng)前狀態(tài): 
  2. 體力:100 
  3. 攻擊力:100 
  4. 防御力: 100 
  5. ----------------- 
  6. 角色當(dāng)前狀態(tài): 
  7. 體力:0 
  8. 攻擊力:0 
  9. 防御力: 0 
  10. ----------------- 
  11. 角色當(dāng)前狀態(tài): 
  12. 體力:100 
  13. 攻擊力:100 
  14. 防御力: 100 

優(yōu)點(diǎn)

備忘錄模式是一種對(duì)象行為型模式,其主要優(yōu)點(diǎn)如下。

  • 提供了一種可以恢復(fù)狀態(tài)的機(jī)制。當(dāng)用戶需要時(shí)能夠比較方便地將數(shù)據(jù)恢復(fù)到某個(gè)歷史的狀態(tài)。
  • 實(shí)現(xiàn)了內(nèi)部狀態(tài)的封裝。除了創(chuàng)建它的發(fā)起人之外,其他對(duì)象都不能夠訪問(wèn)這些狀態(tài)信息。
  • 簡(jiǎn)化了發(fā)起人類。發(fā)起人不需要管理和保存其內(nèi)部狀態(tài)的各個(gè)備份,所有狀態(tài)信息都保存在備忘錄中,并由管理者進(jìn)行管理,這符合單一職責(zé)原則。

缺點(diǎn)

資源消耗大。如果要保存的內(nèi)部狀態(tài)信息過(guò)多或者特別頻繁,將會(huì)占用比較大的內(nèi)存資源。

注意事項(xiàng)

  1. 為了符合迪米特法則,需要有一個(gè)管理備忘錄的類
  2. 不要在頻繁建立備份的場(chǎng)景中使用備忘錄模式。為了節(jié)約內(nèi)存,可使用原型模式+備忘錄模式

應(yīng)用場(chǎng)景

  1. 需要保存和恢復(fù)數(shù)據(jù)的相關(guān)場(chǎng)景
  2. 提供一個(gè)可回滾的操作,如ctrl+z、瀏覽器回退按鈕、Backspace鍵等
  3. 需要監(jiān)控的副本場(chǎng)景

模式的擴(kuò)展

 

在備忘錄模式中,有單狀態(tài)備份的例子,也有多狀態(tài)備份的例子??梢越Y(jié)合原型模式混合使用。在備忘錄模式中,通過(guò)定義“備忘錄”來(lái)備份“發(fā)起人”的信息,而原型模式的 clone() 方法具有自備份功能,所以,如果讓發(fā)起人實(shí)現(xiàn) Cloneable 接口就有備份自己的功能,這時(shí)可以刪除備忘錄類,其結(jié)構(gòu)如下:

源碼中的應(yīng)用

  1. #Spring 
  2. org.springframework.binding.message.StateManageableMessageContext 

StateManageableMessageContext 部分源碼

  1. public interface StateManageableMessageContext extends MessageContext { 
  2.  
  3.    /** 
  4.     * Create a serializable memento, or token representing a snapshot of the internal state of this message context. 
  5.     * @return the messages memento 
  6.     */ 
  7.    public Serializable createMessagesMemento(); 
  8.  
  9.    /** 
  10.     * Set the state of this context from the memento provided. After this call, the messages in this context will match 
  11.     * what is encapsulated inside the memento. Any previous state will be overridden. 
  12.     * @param messagesMemento the messages memento 
  13.     */ 
  14.    public void restoreMessages(Serializable messagesMemento); 
  15.  
  16.    /** 
  17.     * Configure the message source used to resolve messages added to this context. May be set at any time to change how 
  18.     * coded messages are resolved. 
  19.     * @param messageSource the message source 
  20.     * @see MessageContext#addMessage(MessageResolver) 
  21.     */ 
  22.    public void setMessageSource(MessageSource messageSource); 

PS:以上代碼提交在 Github :

https://github.com/Niuh-Study/niuh-designpatterns.git

責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2023-10-07 00:14:53

2024-05-15 17:41:37

備忘錄模式多線程

2023-10-31 09:07:16

備忘錄模式保存

2023-04-19 08:03:52

Go設(shè)計(jì)模式

2025-02-17 14:48:14

2018-12-24 21:40:12

2011-04-11 10:03:32

錢(qián)伯斯思科

2011-08-16 18:38:23

Core Animat動(dòng)畫(huà)

2017-03-21 11:02:59

基礎(chǔ)深度學(xué)習(xí)備忘錄

2014-04-17 10:30:41

Linux 命令黑白備忘錄

2023-10-10 15:26:30

內(nèi)存泄露OOM

2020-10-23 09:40:26

設(shè)計(jì)模式

2020-11-03 13:05:18

命令模式

2020-11-04 08:54:54

狀態(tài)模式

2022-01-12 13:33:25

工廠模式設(shè)計(jì)

2016-03-03 10:09:26

2013-08-29 10:50:48

移動(dòng)網(wǎng)站性能優(yōu)化移動(dòng)web

2018-06-20 13:14:16

MySQL數(shù)據(jù)優(yōu)化查詢備忘錄

2020-11-09 08:20:33

解釋器模式

2020-10-20 13:33:00

建造者模式
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)