一、模式簡介
定義:在不破壞封裝性的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這個狀態,以便以后當需要時能將該對象恢復到原先保存的狀態
場景:需要保存與恢復數據的場景,如玩游戲時中間結果的存檔功能。需要提供一個可回滾操作的場景,如數據庫事務的操作。
- 角色結構:
- 發起人(Originator)角色:記錄當前時刻的內部狀態信息,提供創建備忘錄和恢復備忘錄數據的功能,實現其他業務功能,它可以訪問備忘錄里的所有信息。
- 備忘錄(Memento)角色:負責存儲發起人的內部狀態,在需要的時候提供這些內部狀態給發起人。
- 管理者(Caretaker)角色:對備忘錄進行管理,提供保存與獲取備忘錄的功能,但其不能對備忘錄的內容進行訪問與修改。
二、模式實現
public class Originator { -> 發起者
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Memento create(){
return new Memento(getState());
}
public void CtrlZ(Memento memento){
this.setState(memento.getState());
}
public void CtrlY(Memento memento){
this.setState(memento.getState());
}
}
public class Memento implements Cloneable{ -> 備忘錄
private String state;
private Memento next;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Memento getNext() {
return next;
}
public void setNext(Memento next) {
this.next = next;
}
}
public class Caretaker { -> 管理者
private Memento mementoZ;
private Memento mementoY;
public Memento getMementoZ() {
if (mementoZ != null) {
Memento get = mementoZ;
mementoZ = mementoZ.getNext();
get.setNext(null);
return get;
}
return null;
}
public void setMementoZ(Memento mementoZ) {
if (this.mementoZ != null){
mementoZ.setNext(this.mementoZ);
}
this.mementoZ = mementoZ;
}
public Memento getMementoY() {
if (mementoY != null) {
Memento get = mementoY;
mementoY = mementoY.getNext();
get.setNext(null);
return get;
}
return null;
}
public void setMementoY(Memento mementoY) {
if (this.mementoY != null){
mementoY.setNext(this.mementoY);
}
this.mementoY = mementoY;
}
public void displayY() {
display(mementoY);
}
public void displayZ() {
display(mementoZ);
}
private void display(Memento memento) {
if (memento != null) {
System.out.println(memento.getState());
if (memento.getNext() != null) display(memento.getNext());
}
}
}
以編輯記事本為例子,編輯過程可以先后退到某一時間的進度,再重新前進到某一時間的進度,管理者包含了兩個備忘錄,分別是后退(組合鍵:Ctrl + Z)和前進(組合鍵:Ctrl + Y),發起人通過管理者獲取到備忘錄,輕松回到某一時間的進度。
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("s1");
caretaker.setMementoZ(originator.create());
originator.setState("s2");
caretaker.setMementoZ(originator.create());
originator.setState("s3");
System.out.println("當前狀態:"+originator.getState());
caretaker.setMementoY(originator.create());
originator.CtrlZ(caretaker.getMementoZ());
System.out.println("當前狀態:"+originator.getState());
caretaker.setMementoY(originator.create());
originator.CtrlZ(caretaker.getMementoZ());
System.out.println("當前狀態:"+originator.getState());
caretaker.setMementoZ(originator.create());
originator.CtrlY(caretaker.getMementoY());
System.out.println("當前狀態:"+originator.getState());
caretaker.setMementoZ(originator.create());
originator.CtrlY(caretaker.getMementoY());
System.out.println("當前狀態:"+originator.getState());