兄弟们,老铁们.又到了学习锻炼我们可爱小小大脑的时候了~~~~~ 今天继续来学习设计模式,正所谓一天一个效果不错!!
喝了这碗鸡血,学就完了~~~
执着的攀登者不必去与别人比较自己的形象是否高大,重要的是要多多思考自己前进的脚步是否扎实。
1.备忘录模式定义
备忘录模式又称标记模式.GOF给的定义为:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态.
就像<<大话西游>>中能使时光倒流的"月光宝盒"一样,回到过去.
2. 备忘录模式结构
- 备忘录(Memento)角色:备忘录角色存储“备忘发起角色”的内部状态。“备忘发起角色”根据需要决定备忘录角色存储“备忘发起角色”的哪些内部状态。为了防止“备忘发起角色”以外的其他对象访问备忘录。备忘录实际上有两个接口,“备忘录管理者角色”只能看到备忘录提供的窄接口——对于备忘录角色中存放的属性是不可见的。 “备忘发起角色”则能够看到一个宽接口——能够得到自己放入备忘录角色中属性。
- 备忘发起(Originator)角色:“备忘发起角色”创建一个备忘录,用以记录当前时刻它的内部状态。在需要时使用备忘录恢复内部状态。
- 备忘录管理者(Caretaker)角色:负责保存好备忘录。不能对备忘录的内容进行操作或检查。
窄接口:管理者(Caretaker)对象(和其他除发起人对象之外的任何对象)看到的是备忘录的窄接口(narrow interface),这个窄接口只允许它把备忘录对象传给其他的对象。
宽接口:与管理者对象看到的窄接口相反的是,发起人对象可以看到一个宽接口(wide interface),这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态。
3.备忘录模式实现
3.1 白箱
备忘录角色对任何对象都提供一个宽接口,备忘录角色的内部所存储的状态就对所有对象公开。因此这个实现又叫做“白箱实现”。
"白箱"将发起人角色的状态都存在了一个谁都能看得到的地方,因此破坏了封装性.这种方法实现比较简单,但需要人为的进行规范约束.
负责人角色类
public class Caretaker {
private Memento memento;
/**
* 备忘录的取值方法
*/
public Memento retrieveMemento(){
return this.memento;
}
/**
* 备忘录的赋值方法
*/
public void saveMemento(Memento memento){
this.memento = memento;
}
}
备忘录角色
//备忘录角色
public class Memento {
private String state;
public Memento(String state){
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
发起人角色
//发起人角色
public class Originator {
private String state;
/**
* 工厂方法,返回一个新的备忘录对象
*/
public Memento createMemento(){
return new Memento(state);
}
/**
* 将发起人恢复到备忘录对象所记载的状态
*/
public void restoreMemento(Memento memento){
this.state = memento.getState();
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
System.out.println("当前状态:" + this.state);
}
}
客户端测试
public static void main(String[] args) {
Originator o = new Originator();
Caretaker c = new Caretaker();
//改变负责人对象的状态
o.setState("On");
//创建备忘录对象,并将发起人对象的状态储存起来
c.saveMemento(o.createMemento());
//修改发起人的状态
o.setState("Off");
//恢复发起人对象的状态
System.out.println("恢复发起人状态");
o.restoreMemento(c.retrieveMemento());
System.out.println( "当前状态 :" + o.getState());
}
结果
当前状态:On
当前状态:Off
恢复发起人状态
On
3.2 黑箱
备忘录角色对发起人(Originator)角色对象提供一个宽接口,而为其他对象提供一个窄接口。这样的实现叫做“黑箱实现”。
将备忘录角色设成发起人类的内部类,从而将备忘录角色对象封装在发起人里面;在外部提供一个标识接口MementoIF给负责人以及其他对象。这样,发起人类看到的是备忘录角色的所有接口,而负责人以及其他对象看到的仅仅是标识接口MementoIF所暴露出来的接口。
窄接口
public interface MementoIF {
}
发起人角色类,里面定义了一个内部类Memento,其中接口全是私有的,因此只有它自己和发起人类可以调用。
public class Originator {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
System.out.println("赋值状态:" + state);
}
/**
* 工厂方法,返还一个新的备忘录对象
*/
public MementoIF createMemento(){
return new Memento(state);
}
/**
* 发起人恢复到备忘录对象记录的状态
*/
public void restoreMemento(MementoIF memento){
this.setState(((Memento)memento).getState());
}
private class Memento implements MementoIF{
private String state;
/**
* 构造方法
*/
private Memento(String state){
this.state = state;
}
private String getState() {
return state;
}
private void setState(String state) {
this.state = state;
}
}
}
负责人角色类,以MementoIF为接口的,由于这个接口仅仅是一个标识接口,因此负责人角色不可能改变这个备忘录对象的内容。
public class Caretaker {
private MementoIF memento;
/**
* 备忘录取值方法
*/
public MementoIF retrieveMemento(){
return memento;
}
/**
* 备忘录赋值方法
*/
public void saveMemento(MementoIF memento){
this.memento = memento;
}
}
客户类测试
public static void main(String[] args) {
Originator o = new Originator();
Caretaker c = new Caretaker();
//改变负责人对象的状态
o.setState("On");
//创建备忘录对象,并将发起人对象的状态存储起来
c.saveMemento(o.createMemento());
//修改发起人对象的状态
o.setState("Off");
//恢复发起人对象的状态
o.restoreMemento(c.retrieveMemento());
}
结果
赋值状态:On
赋值状态:Off
赋值状态:On
黑箱很好的解决了白箱的缺陷:采用内部类来控制访问权限.
4.适用场景
- 必须保存一个对象在某一个时刻的(部分)状态, 这样以后需要时它才能恢复到先前的状态。
- 如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象
的封装性。