實(shí)例講解JAVA設(shè)計(jì)模式之備忘錄模式
在講述這個(gè)模式之前,我們先看一個(gè)案例:游戲回檔
游戲的某個(gè)場(chǎng)景,一游戲角色有生命力、攻擊力、防御力等數(shù)據(jù),在打Boss前和后會(huì)不一樣,我們?cè)试S玩家如果感覺與Boss決斗的效果不理想,可以讓游戲恢復(fù)到?jīng)Q斗前。下面是代碼:
游戲角色類,用來存儲(chǔ)角色的生命力、攻擊力、防御力的數(shù)據(jù)。
public class GameRole {
private int vit;//生命力
private int atk;//攻擊力
private int def;//防御力
//狀態(tài)顯示
public void stateDisplay() {
System.out.println("當(dāng)前角色狀態(tài):");
System.out.println("體力:"+this.vit);
System.out.println("攻擊力"+this.atk);
System.out.println("防御力"+this.def);
}
//獲取初始狀態(tài)
public void getInitState() {
//數(shù)據(jù)通常來自本地磁盤或遠(yuǎn)程數(shù)據(jù)庫
this.vit = 100;
this.atk = 100;
this.def = 100;
}
//戰(zhàn)斗
public void fight() {
//在與Boss大戰(zhàn)后游戲數(shù)據(jù)損耗為0
this.vit = 0;
this.atk = 0;
this.def = 0;
}
//省略getter、setter方法
}
//測(cè)試方法
public class Test {
public static void main(String[] args) {
//大戰(zhàn)Boss前
GameRole lixiaoyao = new GameRole();
lixiaoyao.getInitState();//Boss大戰(zhàn)前,獲得角色初始狀態(tài)
lixiaoyao.stateDisplay();
//保存進(jìn)度,通過游戲角色的新實(shí)例來保存進(jìn)度
GameRole backup = new GameRole();
backup.setVit(lixiaoyao.getVit());
backup.setAtk(lixiaoyao.getAtk());
backup.setDef(lixiaoyao.getDef());
//大戰(zhàn)Boss時(shí),損耗嚴(yán)重,所有數(shù)據(jù)全部損耗為0
lixiaoyao.fight();
lixiaoyao.stateDisplay();
//恢復(fù)之前狀態(tài),重新來玩
lixiaoyao.setVit(backup.getVit());
lixiaoyao.setAtk(backup.getAtk());
lixiaoyao.setDef(backup.getDef());
lixiaoyao.stateDisplay();
}
}
上面的代碼實(shí)現(xiàn)了效果,但是不理想的是:main方法里暴露了太多“細(xì)節(jié)”,使得main方法需要知道“生命力、攻擊力、防御力”這樣的細(xì)節(jié)。以后需要增加“魔法值”或修改現(xiàn)有的“生命力”為“經(jīng)驗(yàn)值”,這部分就要修改了。同樣的道理也存在于恢復(fù)時(shí)的代碼。顯然,我們希望的是把這些“游戲角色”的存取狀態(tài)細(xì)節(jié)封裝起來,而且最好是封裝在外部的類中。以體現(xiàn)職責(zé)分離。
下面介紹備忘錄模式:http://chabaoo.cn/article/189469.htm
在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài),這樣以后就可將該對(duì)象恢復(fù)到原先保存的狀態(tài)。
用備忘錄模式優(yōu)化案例
public class GameRole {
private int vit;//生命力
private int atk;//攻擊力
private int def;//防御力
//狀態(tài)顯示
public void stateDisplay() {
System.out.println("當(dāng)前角色狀態(tài):");
System.out.println("體力:"+this.vit);
System.out.println("攻擊力"+this.atk);
System.out.println("防御力"+this.def);
}
//獲取初始狀態(tài)
public void getInitState() {
//數(shù)據(jù)通常來自本地磁盤或遠(yuǎn)程數(shù)據(jù)庫
this.vit = 100;
this.atk = 100;
this.def = 100;
}
//戰(zhàn)斗
public void fight() {
//在與Boss大戰(zhàn)后游戲數(shù)據(jù)損耗為0
this.vit = 0;
this.atk = 0;
this.def = 0;
}
//新增“保存角色狀態(tài)”方法,將游戲角色的三個(gè)狀態(tài)值通過實(shí)例化“角色狀態(tài)存儲(chǔ)箱”返回
public RoleStateMemento saveState() {
return new RoleStateMemento(vit, atk, def);
}
//新增“恢復(fù)角色狀態(tài)”方法,可將外部的“角色狀態(tài)存儲(chǔ)箱”中的狀態(tài)值恢復(fù)給游戲角色
public void recoveryState(RoleStateMemento memento) {
this.vit = memento.getAtk();
this.atk = memento.getAtk();
this.def = memento.getDef();
}
//省略getter、setter方法
}
//角色狀態(tài)存儲(chǔ)箱類
public class RoleStateMemento {
private int vit;//生命力
private int atk;//攻擊力
private int def;//防御力
//將生命力、攻擊力、防御力存入狀態(tài)存儲(chǔ)箱對(duì)象中
public RoleStateMemento(int vit, int atk, int def) {
super();
this.vit = vit;
this.atk = atk;
this.def = def;
}
//省略getter、setter方法
}
//角色狀態(tài)管理者類
public class RoleStateCaretaker {
private RoleStateMemento memento;
public RoleStateMemento getMemento() {
return memento;
}
public void setMemento(RoleStateMemento memento) {
this.memento = memento;
}
}
//測(cè)試方法
public class Test {
public static void main(String[] args) {
//大戰(zhàn)Boss前
GameRole lixiaoyao = new GameRole();
lixiaoyao.getInitState();//Boss大戰(zhàn)前,獲得角色初始狀態(tài)
lixiaoyao.stateDisplay();
//保存進(jìn)度,由于封裝在Memento中,因此我們并不知道保存了哪些具體的數(shù)據(jù)
RoleStateCaretaker stateAdmin = new RoleStateCaretaker();
stateAdmin.setMemento(lixiaoyao.saveState());
//大戰(zhàn)Boss時(shí),損耗嚴(yán)重
lixiaoyao.fight();
lixiaoyao.stateDisplay();
//恢復(fù)之前的狀態(tài)
lixiaoyao.recoveryState(stateAdmin.getMemento());
lixiaoyao.stateDisplay();
}
}
輸出結(jié)果同上。
肯定有人會(huì)問:對(duì)于“角色狀態(tài)”的保存,直接調(diào)用RoleStateMemento進(jìn)行set和get不就行了,為什么還需要一個(gè)RoleStateCaretaker類呢?
這是為了符合迪米特法則進(jìn)行的優(yōu)化!
備忘錄模式也是有缺點(diǎn)的,角色狀態(tài)需要完整存儲(chǔ)到備忘錄對(duì)象中,如果狀態(tài)數(shù)據(jù)很大很多,那么在資源消耗上,備忘錄對(duì)象會(huì)非常耗內(nèi)存。所以也不是用的越多越好。
以上就是實(shí)例講解JAVA設(shè)計(jì)模式之備忘錄模式的詳細(xì)內(nèi)容,更多關(guān)于JAVA 備忘錄模式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Java設(shè)計(jì)模式初識(shí)之備忘錄模式詳解
- Java設(shè)計(jì)模式之備忘錄模式
- 深入理解Java設(shè)計(jì)模式之備忘錄模式
- Java設(shè)計(jì)模式之java備忘錄模式詳解
- JAVA設(shè)計(jì)模式之備忘錄模式原理與用法詳解
- 詳解備忘錄模式及其在Java設(shè)計(jì)模式編程中的實(shí)現(xiàn)
- 詳解Java設(shè)計(jì)模式之備忘錄模式的使用
- Java設(shè)計(jì)模式之備忘錄模式(Memento模式)介紹
- Java設(shè)計(jì)模式之備忘錄模式實(shí)現(xiàn)對(duì)象狀態(tài)的保存和恢復(fù)
相關(guān)文章
Mybatis一對(duì)多關(guān)聯(lián)關(guān)系映射實(shí)現(xiàn)過程解析
這篇文章主要介紹了Mybatis一對(duì)多關(guān)聯(lián)關(guān)系映射實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
SpringBoot+aop實(shí)現(xiàn)主從數(shù)據(jù)庫的讀寫分離操作
讀寫分離的作用是為了緩解寫庫,也就是主庫的壓力,但一定要基于數(shù)據(jù)一致性的原則,就是保證主從庫之間的數(shù)據(jù)一定要一致,這篇文章給大家介紹SpringBoot+aop實(shí)現(xiàn)主從數(shù)據(jù)庫的讀寫分離操作,感興趣的朋友跟隨小編一起看看吧2024-03-03
Java中Redis存儲(chǔ)String類型會(huì)有亂碼的問題及解決方案
在java中使用Redis存儲(chǔ)String類型的數(shù)據(jù)時(shí),會(huì)出現(xiàn)亂碼,我寫了一條存儲(chǔ)key為name,值為虎哥的字符串,然后獲取一下這個(gè)key為name的值,打印得到的值,下面通過實(shí)例代碼介紹Java中Redis存儲(chǔ)String類型會(huì)有亂碼的問題及解決方案,一起看看吧2024-04-04
學(xué)習(xí)不同 Java.net 語言中類似的函數(shù)結(jié)構(gòu)
這篇文章主要介紹了學(xué)習(xí)不同 Java.net 語言中類似的函數(shù)結(jié)構(gòu),函數(shù)式編程語言包含多個(gè)系列的常見函數(shù)。但開發(fā)人員有時(shí)很難在語言之間進(jìn)行切換,因?yàn)槭煜さ暮瘮?shù)具有不熟悉的名稱。函數(shù)式語言傾向于基于函數(shù)范例來命名這些常見函數(shù)。,需要的朋友可以參考下2019-06-06

