設計模式的藝術 行為型模式之備忘錄模式
阿新 • • 發佈:2018-11-01
前言
每個人都會有後悔的時候,可是人生沒有後悔藥,做過的事情無法再去後悔,軟體設計中卻是有這麼一種後悔機制,叫做備忘錄模式,它就是軟體中的"後悔藥"
什麼是備忘錄模式 Memento Pattern
在不破壞封裝的前提下,捕獲一個物件的內部狀態,並在物件之外儲存這個狀態,這樣可以將物件恢復到原先儲存的狀態,它是一種物件行為型模式,有個別名叫做Token
備忘錄模式的優點
(1)、它提供了一種狀態恢復的實現機制,使得使用者可以方便地回到一個特定的歷史步驟,當新的狀態無效或者存在問題時,可以使用暫時儲存的備忘錄將狀態復原
(2)、備忘錄實現了對資訊的封裝,一個備忘錄物件是一種原發器物件狀態的表示,不會被其他程式碼所改動,備忘錄儲存了原發器的狀態,採用列表,堆疊等集合來儲存備忘錄物件可以實現多次撤銷操作。
備忘錄模式的主要缺點
資源消耗過大,如果需要儲存的原發器類的成員變數太多,就不可避免地需要佔用大量的儲存空間,每儲存一次物件的狀態都需要消耗一定的系統資源。
備忘錄模式的適用場景
(1)、儲存一個物件在某一個時刻的全部狀態或部分狀態,這樣以後需要時就能恢復到先前的狀態,實現撤銷操作
(2)、防止外界物件破壞一個物件歷史狀態的封裝性,避免將物件歷史狀態的實現細節暴露給外界物件
備忘錄模式的具體實現
目錄結構
原發器
package com.company; //象棋棋子類:原發器 public class Chessman { private String label; private int x; private int y; public Chessman(String label, int x, int y) { this.label = label; this.x = x; this.y = y; } //儲存狀態 public ChessmanMemento save(){ return new ChessmanMemento(this.label,this.x,this.y); } //恢復狀態 public void restore(ChessmanMemento memento){ this.label=memento.getLabel(); this.y=memento.getY(); this.x=memento.getX(); } public String getLabel() { return label; } public void setLabel(String label) { this.label = label; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } }
備忘錄
package com.company; //棋子備忘錄 public class ChessmanMemento { private String label; private int x; private int y; public ChessmanMemento(String label, int x, int y) { this.label = label; this.x = x; this.y = y; } public String getLabel() { return label; } public void setLabel(String label) { this.label = label; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } }
備忘錄管理類
package com.company;
import java.util.ArrayList;
//象棋棋子備忘錄管理類:負責人
public class MementoCaretaker {
/* private ChessmanMemento memento;
public ChessmanMemento getMemento() {
return memento;
}
public void setMemento(ChessmanMemento memento) {
this.memento = memento;
}*/
//定義一個集合來儲存多個備忘錄
private ArrayList mementoList=new ArrayList();
public ChessmanMemento getMemento(int i) {
return (ChessmanMemento) mementoList.get(i);
}
public void setMemento(ChessmanMemento memento) {
mementoList.add(memento);
}
}
測試類
package com.company;
public class Client {
private static int index = -1; //定義一個索引來記錄當前狀態所在的位置
private static MementoCaretaker mc = new MementoCaretaker();
public static void main(String[] args) {
Chessman chess = new Chessman("車", 1, 1);
display(chess);
chess.setX(4);
display(chess);
chess.setX(5);
display(chess);
undo(chess, index);
undo(chess, index);
redo(chess, index);
redo(chess, index);
}
//撤銷悔棋
private static void redo(Chessman chess, int index) {
System.out.println("撤銷悔棋");
index++;
chess.restore(mc.getMemento(index+1)); //恢復到下一個備忘錄
System.out.println("棋子" + chess.getLabel() + "當前位置為:" + "第" + chess.getX() + "行" + "第" + chess.getY() + "行。");
}
//悔棋
private static void undo(Chessman chess, int index) {
System.out.println("悔棋");
index--;
chess.restore(mc.getMemento(index-1)); //撤銷到上個備忘錄
System.out.println("棋子" + chess.getLabel() + "當前位置為:" + "第" + chess.getX() + "行" + "第" + chess.getY() + "行。");
}
private static void display(Chessman chess) {
mc.setMemento(chess.save()); //儲存在備忘錄
index++;
System.out.println("棋子" + chess.getLabel() + "當前位置為:" + "第" + chess.getX() + "行" + "第" + chess.getY() + "行。");
}
}
轉載請註明出處,掌聲送給社會人