网站建设 昆明 价格/优化网络的软件
《设计模式》备忘录模式
定义:
- 备忘录模式又称为快照模式或者令牌模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
- 属性行为型模式。
备忘录模式的角色组成:
- Originator(发起人):负责创建一个 Memento(备忘录),用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。
- Memento(备忘录):负责存储 Originator(发起人) 对象的内部状态,并可防止发起人以外的其他对象访问备忘录。
- Caretaker(管理者):负责存储、提供并管理备忘录,无法对备忘录的内容进行操作和访问。只负责存储对象,而不能修改对象,也无须知道对象的实现细节。
访问者模式的 UML 类图:
🎈情景案例:平时在写博客文章时,可能写到一半因为其他事中止了,这时通常将写好的内容保存到草稿(这时就是创建了一个备忘录),等有空时(或者是几天后几周后都可能)再从草稿箱中找回当时的草稿(恢复当时状态)继续撰写文章,这就是一个典型的备忘录模式的应用。
发起者 Originator 类:
public class Originator {private String state;public void setMemento(Memento memento) {state = memento.getState();}public Memento createMemento() {return new Memento(this);}public String getState() {return state;}public void setState(String state) {this.state = state;}
}
备忘录 Memento 类:
class Memento {private String state;public Memento(Originator originator) {state = originator.getState();}public String getState() {return state;}public void setState(String state) {this.state = state;}
}
备忘录管理者 Caretaker 类:
public class Caretaker {private Memento memento;public Memento getMemento() {return memento;}public void setMemento(Memento memento) {this.memento = memento;}
}
客户端 Client 类:
public class Client {public static void main(String[] args) {// 创建发起者Originator originator = new Originator();originator.setState("文章进度50%");// 创建备忘录管理者Caretaker caretaker = new Caretaker();// 备忘录管理者暂存发起者目前的状态caretaker.setMemento(originator.createMemento());originator.setState("午休醒来朦胧状态接着午休前又写了10%,清醒之后发现写的不对,赶紧撤销修改~");// 撤销修改,恢复备忘录中保存的状态originator.setMemento(caretaker.getMemento());}
}
✨在设计备忘录类时需要考虑其封装性,除了
Originator
类,不允许其他类来调用备忘录类Memento
的构造函数与相关方法。如果不考虑封装性,允许其他类调用setState()
等方法,将导致在备忘录中保存的历史状态发生改变,通过撤销操作所恢复的状态就不再是真实的历史状态,备忘录模式也就失去了本身的意义。
备忘录模式的优点:
- 实现了对信息的封装:将复杂的对象内部信息对其他的对象屏蔽,从而保持封装的边界。
- 提供了对状态回滚的支持:使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。
备忘录模式的缺点:
- 资源消耗大:如果需要保存的状态过多,则每一次保存都会消耗很多内存。
备忘录模式的适用场景:
- 保存一个对象在某一个时刻的全部状态或部分状态,这样以后需要时就能够恢复到先前的状态,实现撤销操作。
- 防止外界对象破坏一个对象历史状态的封装性,避免将对象历史状态的实现细节暴露给外界对象。
🎈备忘录模式在工具包 com.sun.corba.se.impl.encoding 中的引用
com.sun.corba.se.impl.encoding.CDRInputStream_1_0
是 CORBA(Common Object Request Broker Architecture)
标准中定义的一种编解码器,它用于将Java对象序列化为二进制格式,以便在网络上进行传输。
CDRInputStream_1_0
中定义了一个名为 StreamMemento
的内部类,用于保存和恢复当前输入流的状态。StreamMemento
类包含了输入流当前位置、缓冲区状态等信息,以便在需要的时候恢复输入流的状态。
CDRInputStream_1_0
源码:
public class CDRInputStream_1_0 extends CDRInputStreamBaseimplements RestorableInputStream {// 此处省略若干行代码// Mark and reset -------------------------------------------------protected MarkAndResetHandler markAndResetHandler = null;protected class StreamMemento{// These are the fields that may change after marking// the stream position, so we need to save them.private int blockLength_;private int end_flag_;private int chunkedValueNestingLevel_;private int valueIndirection_;private int stringIndirection_;private boolean isChunked_;private javax.rmi.CORBA.ValueHandler valueHandler_;private ByteBufferWithInfo bbwi_;private boolean specialNoOptionalDataState_;public StreamMemento(){blockLength_ = blockLength;end_flag_ = end_flag;chunkedValueNestingLevel_ = chunkedValueNestingLevel;valueIndirection_ = valueIndirection;stringIndirection_ = stringIndirection;isChunked_ = isChunked;valueHandler_ = valueHandler;specialNoOptionalDataState_ = specialNoOptionalDataState;bbwi_ = new ByteBufferWithInfo(bbwi);}}public java.lang.Object createStreamMemento() {return new StreamMemento();}public void restoreInternalState(java.lang.Object streamMemento) {StreamMemento mem = (StreamMemento)streamMemento;blockLength = mem.blockLength_;end_flag = mem.end_flag_;chunkedValueNestingLevel = mem.chunkedValueNestingLevel_;valueIndirection = mem.valueIndirection_;stringIndirection = mem.stringIndirection_;isChunked = mem.isChunked_;valueHandler = mem.valueHandler_;specialNoOptionalDataState = mem.specialNoOptionalDataState_;bbwi = mem.bbwi_;}public int getPosition() {return get_offset();}public void mark(int readlimit) {markAndResetHandler.mark(this);}public void reset() {markAndResetHandler.reset();}// ---------------------------------- end Mark and Reset
}
在 CDRInputStream_1_0
中,备忘录模式的应用,可以让输入流在需要恢复状态时,能够快速且准确地恢复到之前保存的状态,提高编解码的效率和可靠性。