日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

簡說設(shè)計模式——備忘錄模式

 頭號碼甲 2020-07-03

一、什么是備忘錄模式

  備忘錄這個詞匯大家應(yīng)該都不陌生,我就經(jīng)常使用備忘錄來記錄一些比較重要的或者容易遺忘的信息,與之相關(guān)的最常見的應(yīng)用有許多,比如游戲存檔,我們玩游戲的時候肯定有存檔功能,旨在下一次登錄游戲時可以從上次退出的地方繼續(xù)游戲,或者對復(fù)活點(diǎn)進(jìn)行存檔,如果掛掉了則可以讀取復(fù)活點(diǎn)的存檔信息重新開始。與之相類似的就是數(shù)據(jù)庫的事務(wù)回滾,或者重做日志redo log等。

  備忘錄模式(Memento),在不破壞封裝性的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存著這個狀態(tài)。這樣以后就可將該對象恢復(fù)到原先保存的狀態(tài)。UML結(jié)構(gòu)圖如下:

  其中,Originator是發(fā)起人,負(fù)責(zé)創(chuàng)建一個備忘錄Memento,用以記錄當(dāng)前時刻它的內(nèi)部狀態(tài),并可使用備忘錄恢復(fù)內(nèi)部狀態(tài);Memento是備忘錄,負(fù)責(zé)存儲Originator對象的內(nèi)部狀態(tài),并可防止Originator以外的其他對象訪問備忘錄Memento;Caretaker是管理者,負(fù)責(zé)保存好備忘錄的Memento,不能對備忘錄的內(nèi)容進(jìn)行操作或檢查。

  1. 發(fā)起人角色

  記錄當(dāng)前時刻的內(nèi)部狀態(tài),并負(fù)責(zé)創(chuàng)建和恢復(fù)備忘錄數(shù)據(jù),允許訪問返回到先前狀態(tài)所需的所有數(shù)據(jù)。

 1 public class Originator { 2      3     private String state; 4  5     public String getState() { 6         return state; 7     } 8  9     public void setState(String state) {10         this.state = state;11     }12     13     public Memento createMento() {14         return (new Memento(state));15     }16     17     public void setMemento(Memento memento) {18         state = memento.getState();19     }20     21     public void show() {22         System.out.println("state = " + state);23     }24     25 }

  2. 備忘錄角色

  負(fù)責(zé)存儲Originator發(fā)起人對象的內(nèi)部狀態(tài),在需要的時候提供發(fā)起人需要的內(nèi)部狀態(tài)。

 1 public class Memento { 2      3     private String state; 4      5     public Memento(String state) { 6         this.state = state; 7     } 8      9     public String getState() {10         return state;11     }12 13 }

  3. 備忘錄管理員角色

  對備忘錄進(jìn)行管理、保存和提供備忘錄,只能將備忘錄傳遞給其他角色。

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

  4. Client客戶端

  下面編寫一小段代碼測試一下,即先將狀態(tài)置為On,保存后再將狀態(tài)置為Off,然后通過備忘錄管理員角色恢復(fù)初始狀態(tài)。

 1 public class Client { 2      3     public static void main(String[] args) { 4         Originator originator = new Originator(); 5         originator.setState("On");    //Originator初始狀態(tài) 6         originator.show(); 7          8         Caretaker caretaker = new Caretaker(); 9         caretaker.setMemento(originator.createMento());10         11         originator.setState("Off");    //Originator狀態(tài)變?yōu)镺ff12         originator.show();13         14         originator.setMemento(caretaker.getMemento());    //回復(fù)初始狀態(tài)15         originator.show();16     }17 18 }

  運(yùn)行結(jié)果如下:

  

二、備忘錄模式的應(yīng)用

  1. 何時使用

  • 需要記錄一個對象的內(nèi)部狀態(tài)時,為了允許用戶取消不確定或者錯誤的操作,能夠恢復(fù)到原先的狀態(tài)

  2. 方法

  • 通過一個備忘錄類專門存儲對象狀態(tài)

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

  • 給用戶提供了一種可以恢復(fù)狀態(tài)的機(jī)制,可以使用能夠比較方便地回到某個歷史的狀態(tài)

  • 實(shí)現(xiàn)了信息的封裝,使得用戶不需要關(guān)心狀態(tài)的保存細(xì)節(jié)

  4. 缺點(diǎn)

  • 消耗資源

  5. 使用場景

  • 需要保存和恢復(fù)數(shù)據(jù)的相關(guān)場景

  • 提供一個可回滾的操作,如ctrl+z、瀏覽器回退按鈕、Backspace鍵等

  • 需要監(jiān)控的副本場景

  6. 應(yīng)用實(shí)例

  • 游戲存檔

  • ctrl+z鍵、瀏覽器回退鍵等(撤銷/還原)

  • 棋盤類游戲的悔棋

  • 數(shù)據(jù)庫事務(wù)的回滾

  7. 注意事項(xiàng)

  • 為了符合迪米特法則,需要有一個管理備忘錄的類

  • 不要在頻繁建立備份的場景中使用備忘錄模式。為了節(jié)約內(nèi)存,可使用原型模式+備忘錄模式

三、備忘錄模式的實(shí)現(xiàn)

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

  1. 游戲角色

  簡單記錄了游戲角色的生命力、攻擊力、防御力,通過saveState()方法來保存當(dāng)前狀態(tài),通過recoveryState()方法來恢復(fù)角色狀態(tài)。

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

  2. 角色狀態(tài)存儲箱

  備忘錄類,用于存儲角色狀態(tài)。

 1 public 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     }36     37 }

  3. 角色狀態(tài)管理者

  備忘錄管理者。

 1 public 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     }12 13 }

  4. Client客戶端

  下面編寫一個簡單的程序測試一下,編寫邏輯大致為打boss前存檔,打boss失敗了,讀檔。

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

  運(yùn)行結(jié)果如下:

  

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多