應(yīng)用場(chǎng)景:需要保存對(duì)象的狀態(tài)和值。
1. 簡(jiǎn)介
public interface Memento {
}public class Originator {//表示原發(fā)器的狀態(tài) private String state =
"";public Memento createMemento() {//創(chuàng)建保存原發(fā)器對(duì)象的狀態(tài)的備忘錄對(duì)象 return new
MementoImpl(state
);}//重新設(shè)置原發(fā)器對(duì)象的狀態(tài),讓其回到備忘錄對(duì)象記錄的狀態(tài) public void setMemento(Memento memento) {MementoImpl mementoImpl =
(MementoImpl
)memento
;this.state = mementoImpl.
getState();}//真正的備忘錄對(duì)象,實(shí)現(xiàn)備忘錄窄接口 private static class MementoImpl implements Memento{ private String state =
"";public MementoImpl(String state){this.state = state
;}public String getState() {return state
;}}
}public class Caretaker{ private Memento memento = null
; public void saveMemento(Memento memento){this.memento = memento
;} public Memento retriveMemento(){return this.memento
;}
}
2. 應(yīng)用到場(chǎng)景
2.1. 創(chuàng)建備忘錄
2.2. 從備忘錄恢復(fù)
public interface FlowAMockMemento extends Serializable{
}public class FlowAMementoCareTaker {//記錄被保存的備忘錄對(duì)象 private FlowAMockMemento memento = null
;//保存?zhèn)渫泴?duì)象 public void saveMemento(FlowAMockMemento memento){this.memento = memento
;}// 獲取被保存的備忘錄對(duì)象 public FlowAMockMemento retriveMemento(){return this.memento
;}
}public class FlowAMementoFileCareTaker { //保存?zhèn)渫泴?duì)象 public void saveMemento(FlowAMockMemento memento){//寫到文件中ObjectOutputStream out = null
;try{out = new
ObjectOutputStream(new
BufferedOutputStream(new
FileOutputStream("FlowAMemento")));out.
writeObject(memento
);...
}//獲取被保存的備忘錄對(duì)象 public FlowAMockMemento retriveMemento(){FlowAMockMemento memento = null
;//從文件中獲取備忘錄數(shù)據(jù)ObjectInputStream in = null
;try{in = new
ObjectInputStream(new
BufferedInputStream(new
FileInputStream("FlowAMemento")));memento =
(FlowAMockMemento
)in.
readObject();...return memento
;}
}public class FlowAMock implements Serializable {//流程名稱,不需要外部存儲(chǔ)的狀態(tài)數(shù)據(jù) private String flowName
; //示意,代指某個(gè)中間結(jié)果,需要外部存儲(chǔ)的狀態(tài)數(shù)據(jù) private int tempResult
; //示意,代指某個(gè)中間結(jié)果,需要外部存儲(chǔ)的狀態(tài)數(shù)據(jù) private String tempState
; //構(gòu)造方法,傳入流程名稱 public FlowAMock(String flowName){this.flowName = flowName
;}//示意,運(yùn)行流程的第一個(gè)階段 public void runPhaseOne(){//在這個(gè)階段,可能產(chǎn)生了中間結(jié)果,示意一下tempResult = 3
;tempState =
"PhaseOne";}//示意,按照方案一來(lái)運(yùn)行流程后半部分 public void schema1(){ this.tempState +=
",Schema1";//示意,需要使用第一個(gè)階段產(chǎn)生的數(shù)據(jù)System.out.
println(this.tempState +
" : now run "+tempResult
);this.tempResult += 11
;} public void schema2(){ } //創(chuàng)建保存原發(fā)器對(duì)象的狀態(tài)的備忘錄對(duì)象 public FlowAMockMemento createMemento() {return new
MementoImpl(this.tempResult,this.tempState
);}//重新設(shè)置原發(fā)器對(duì)象的狀態(tài),讓其回到備忘錄對(duì)象記錄的狀態(tài) public void setMemento(FlowAMockMemento memento) {MementoImpl mementoImpl =
(MementoImpl
)memento
;this.tempResult = mementoImpl.
getTempResult();this.tempState = mementoImpl.
getTempState();}//真正的備忘錄對(duì)象,實(shí)現(xiàn)備忘錄窄接口 private static class MementoImpl implements FlowAMockMemento{ private int tempResult
;//示意,保存某個(gè)中間結(jié)果 private String tempState
;//示意,保存某個(gè)中間結(jié)果public MementoImpl(int tempResult,String tempState){this.tempResult = tempResult
;this.tempState = tempState
;}public int getTempResult() {return tempResult
;}public String getTempState() {return tempState
;}}
}public class FlowAMockPrototype implements Cloneable { private String flowName
; private int tempResult
;//示意,代指某個(gè)中間結(jié)果,需要外部存儲(chǔ)的狀態(tài)數(shù)據(jù) private String tempState
;public FlowAMockPrototype(String flowName){this.flowName = flowName
;}//示意,運(yùn)行流程的第一個(gè)階段 public void runPhaseOne(){//在這個(gè)階段,可能產(chǎn)生了中間結(jié)果,示意一下tempResult = 3
;tempState =
"PhaseOne";}//示意,按照方案一來(lái)運(yùn)行流程后半部分 public void schema1(){//示意,需要使用第一個(gè)階段產(chǎn)生的數(shù)據(jù)
} public void schema2(){ } //創(chuàng)建保存原發(fā)器對(duì)象的狀態(tài)的備忘錄對(duì)象 public FlowAMockMemento createMemento() { return new
MementoImplPrototype((FlowAMockPrototype
) this.
clone()); } //重新設(shè)置原發(fā)器對(duì)象的狀態(tài),讓其回到備忘錄對(duì)象記錄的狀態(tài) public void setMemento(FlowAMockMemento memento) {MementoImplPrototype mementoImpl =
(MementoImplPrototype
)memento
;this.tempResult = mementoImpl.
getFlowAMock().tempResult
;this.tempState = mementoImpl.
getFlowAMock().tempState
;}//真正的備忘錄對(duì)象,實(shí)現(xiàn)備忘錄窄接口,// 實(shí)現(xiàn)成私有的內(nèi)部類,不讓外部訪問 private static class MementoImplPrototype implements FlowAMockMemento{private FlowAMockPrototype flowAMock = null
; public MementoImplPrototype(FlowAMockPrototype f){this.flowAMock = f
;} public FlowAMockPrototype getFlowAMock() {return flowAMock
;}}
}public static void main(String[] args) {// 創(chuàng)建模擬運(yùn)行流程的對(duì)象FlowAMock mock = new
FlowAMock("TestFlow");//運(yùn)行流程的第一個(gè)階段mock.
runPhaseOne();//創(chuàng)建一個(gè)管理者FlowAMementoCareTaker careTaker = new
FlowAMementoCareTaker();//創(chuàng)建此時(shí)對(duì)象的備忘錄對(duì)象,并保存到管理者對(duì)象那里,后面要用FlowAMockMemento memento = mock.
createMemento();careTaker.
saveMemento(memento
);//按照方案一來(lái)運(yùn)行流程后半部分mock.
schema1();//從管理者獲取備忘錄對(duì)象,然后設(shè)置回去,//讓模擬運(yùn)行流程的對(duì)象自己恢復(fù)自己的內(nèi)部狀態(tài)mock.
setMemento(careTaker.
retriveMemento());//按照方案二來(lái)運(yùn)行流程后半部分mock.
schema2();}
3. redo/undo借助備忘錄模式
// todo
4. 總結(jié)
備忘錄模式的本質(zhì):保存和恢復(fù)內(nèi)部狀態(tài)
-
如果必須保存一個(gè)對(duì)象在某一個(gè)時(shí)刻的全部或者部分狀態(tài),方便在以后需要的時(shí)候把該對(duì)象恢復(fù)到先前的狀態(tài),可以使用備忘錄模式。
-
使用備忘錄對(duì)象來(lái)封裝和保存需要保存的內(nèi)部狀態(tài),然后把備忘錄對(duì)象保存到管理者對(duì)象中,在需要的時(shí)候,再?gòu)墓芾碚邔?duì)象中獲取備忘錄對(duì)象,來(lái)恢復(fù)對(duì)象的狀態(tài)。
-
如果需要保存一個(gè)對(duì)象的內(nèi)部狀態(tài),但是如果用接口來(lái)讓其他對(duì)象直接得到這些需要保存的狀態(tài),將會(huì)暴露對(duì)象的實(shí)現(xiàn)細(xì)節(jié)并破壞對(duì)象的封裝性,這時(shí)可以使用備忘錄模式,把備忘錄對(duì)象實(shí)現(xiàn)成為原發(fā)器對(duì)象的內(nèi)部類,而且還是私有的,從而保證只有原發(fā)器對(duì)象才能訪問該備忘錄對(duì)象。這樣既保存了需要保存的狀態(tài),又不會(huì)暴露原發(fā)器對(duì)象的內(nèi)部實(shí)現(xiàn)細(xì)節(jié)。
總結(jié)
以上是生活随笔為你收集整理的《研磨设计模式》chap19 备忘录模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。