歡迎您光臨本站 註冊首頁

實例講解JAVA設計模式之備忘錄模式

←手機掃碼閱讀     e36605 @ 2020-06-26 , reply:0

在講述這個模式之前,我們先看一個案例:遊戲回檔

遊戲的某個場景,一遊戲角色有生命力、攻擊力、防禦力等數據,在打Boss前和後會不一樣,我們允許玩家如果感覺與Boss決鬥的效果不理想,可以讓遊戲恢復到決鬥前。下面是代碼:

遊戲角色類,用來存儲角色的生命力、攻擊力、防禦力的數據。

  public class GameRole {   private int vit;//生命力   private int atk;//攻擊力   private int def;//防禦力      //狀態顯示   public void stateDisplay() {    System.out.println("當前角色狀態:");    System.out.println("體力:"+this.vit);    System.out.println("攻擊力"+this.atk);    System.out.println("防禦力"+this.def);   }   //獲取初始狀態   public void getInitState() {    //數據通常來自本地磁盤或遠程數據庫    this.vit = 100;    this.atk = 100;    this.def = 100;   }   //戰鬥   public void fight() {    //在與Boss大戰後遊戲數據損耗為0    this.vit = 0;    this.atk = 0;    this.def = 0;   }   //省略getter、setter方法     }  //測試方法  public class Test {   public static void main(String[] args) {    //大戰Boss前    GameRole lixiaoyao = new GameRole();    lixiaoyao.getInitState();//Boss大戰前,獲得角色初始狀態    lixiaoyao.stateDisplay();        //保存進度,通過遊戲角色的新實例來保存進度    GameRole backup = new GameRole();    backup.setVit(lixiaoyao.getVit());    backup.setAtk(lixiaoyao.getAtk());    backup.setDef(lixiaoyao.getDef());        //大戰Boss時,損耗嚴重,所有數據全部損耗為0    lixiaoyao.fight();    lixiaoyao.stateDisplay();        //恢復之前狀態,重新來玩    lixiaoyao.setVit(backup.getVit());    lixiaoyao.setAtk(backup.getAtk());    lixiaoyao.setDef(backup.getDef());    lixiaoyao.stateDisplay();       }  }

 

上面的代碼實現了效果,但是不理想的是:main方法裡暴露了太多“細節”,使得main方法需要知道“生命力、攻擊力、防禦力”這樣的細節。以後需要增加“魔法值”或修改現有的“生命力”為“經驗值”,這部分就要修改了。同樣的道理也存在於恢復時的代碼。顯然,我們希望的是把這些“遊戲角色”的存取狀態細節封裝起來,而且最好是封裝在外部的類中。以體現職責分離。

下面介紹備忘錄模式:https://www.jb51.net/article/189469.htm

在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態,這樣以後就可將該對象恢復到原先保存的狀態。

用備忘錄模式優化案例

  public class GameRole {   private int vit;//生命力   private int atk;//攻擊力   private int def;//防禦力      //狀態顯示   public void stateDisplay() {    System.out.println("當前角色狀態:");    System.out.println("體力:"+this.vit);    System.out.println("攻擊力"+this.atk);    System.out.println("防禦力"+this.def);   }   //獲取初始狀態   public void getInitState() {    //數據通常來自本地磁盤或遠程數據庫    this.vit = 100;    this.atk = 100;    this.def = 100;   }   //戰鬥   public void fight() {    //在與Boss大戰後遊戲數據損耗為0    this.vit = 0;    this.atk = 0;    this.def = 0;   }   //新增“保存角色狀態”方法,將遊戲角色的三個狀態值通過實例化“角色狀態存儲箱”返回   public RoleStateMemento saveState() {    return new RoleStateMemento(vit, atk, def);   }      //新增“恢復角色狀態”方法,可將外部的“角色狀態存儲箱”中的狀態值恢復給遊戲角色   public void recoveryState(RoleStateMemento memento) {    this.vit = memento.getAtk();    this.atk = memento.getAtk();    this.def = memento.getDef();   }      //省略getter、setter方法     }  //角色狀態存儲箱類  public class RoleStateMemento {   private int vit;//生命力   private int atk;//攻擊力   private int def;//防禦力   //將生命力、攻擊力、防禦力存入狀態存儲箱對象中   public RoleStateMemento(int vit, int atk, int def) {    super();    this.vit = vit;    this.atk = atk;    this.def = def;   }      //省略getter、setter方法     }  //角色狀態管理者類  public class RoleStateCaretaker {   private RoleStateMemento memento;     public RoleStateMemento getMemento() {    return memento;   }     public void setMemento(RoleStateMemento memento) {    this.memento = memento;   }     }  //測試方法  public class Test {   public static void main(String[] args) {    //大戰Boss前    GameRole lixiaoyao = new GameRole();    lixiaoyao.getInitState();//Boss大戰前,獲得角色初始狀態    lixiaoyao.stateDisplay();        //保存進度,由於封裝在Memento中,因此我們並不知道保存了哪些具體的數據    RoleStateCaretaker stateAdmin = new RoleStateCaretaker();    stateAdmin.setMemento(lixiaoyao.saveState());        //大戰Boss時,損耗嚴重    lixiaoyao.fight();    lixiaoyao.stateDisplay();        //恢復之前的狀態    lixiaoyao.recoveryState(stateAdmin.getMemento());    lixiaoyao.stateDisplay();       }  }

 

輸出結果同上。

肯定有人會問:對於“角色狀態”的保存,直接調用RoleStateMemento進行set和get不就行了,為什麼還需要一個RoleStateCaretaker類呢?

這是為了符合迪米特法則進行的優化!

備忘錄模式也是有缺點的,角色狀態需要完整存儲到備忘錄對象中,如果狀態數據很大很多,那麼在資源消耗上,備忘錄對象會非常耗內存。所以也不是用的越多越好。

 


[e36605 ] 實例講解JAVA設計模式之備忘錄模式已經有218次圍觀

http://coctec.com/docs/java/show-post-239771.html