备忘录模式

  备忘录模式:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象以外保存这个状态。这样之后就可将该对象恢复到原先保存的状态。java

  涉及角色:测试

  1.Originator(发起人):负责建立一个备忘录Memento,用以记录当前时刻自身的内部状态,并可以使用备忘录恢复内部状态。Originator能够根据须要决定Memento存储本身的哪些内部状态。this

  2.Memento(备忘录):负责存储Originator对象的内部状态,并能够防止Originator之外的其余对象访问备忘录。备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其余对象。Originator却可看到备忘录的宽接口,容许它访问返回到先前状态所须要的全部数据。spa

  3.Caretaker(管理者):负责备忘录Memento,不能对Memento的内容进行访问或者操做。3d

  关于宽窄接口,java中有三种实现code

  第一种就是采用两个不一样的接口类来限制访问权限。这两个接口类中,一个提供比较完备的操做状态的方法,咱们称它为宽接口;而另外一个则能够只是一个标示,咱们称它为窄接口。备忘录角色要实现这两个接口类。这样对于“备忘发起角色”采用宽接口进行访问,而对于其余的角色或者对象则采用窄接口进行访问。这种实现比较简单,可是须要人为的进行规范约束——而这每每是没有力度的。对象

  第二种方法便很好的解决了第一种的缺陷:采用内部类来控制访问权限。将备忘录角色做为“备忘发起角色”的一个私有内部类。blog

  第三种方式是不太推荐使用的:使用clone方法来简化备忘录模式。因为Java提供了clone机制,这使得复制一个对象变得轻松起来。使用了clone机制的备忘录模式,备忘录角色基本能够省略了,并且能够很好的保持对象的封装。可是在为你的类实现clone方法时要慎重啊。接口

  我的比较推荐第二种方式,这也是许多开源项目使用的方式,下面是在网上找的一个类图资源

  demo以下:

  发起者和备忘录,备忘录类为发起者的一个内部类

package memento;

public class Hero {

    private Integer bloodVolume;
    
    private Integer magicPoint;
    public Hero(Integer bloodVolume,Integer magicPoint) {
        this.bloodVolume = bloodVolume;
        this.magicPoint = magicPoint;
    }
    
    public void show() {
        System.out.println("bloodVolume:" +bloodVolume +",magicPoint" + magicPoint);
    }
    public StatusMemento saveStatus() {
        return new StatusMemento(bloodVolume,magicPoint);
    }
    
    public void fight() {
        this.bloodVolume -=5;
        this.magicPoint=0;
    }
    
    public void recover(MementoInterface mementoInterface) {
        StatusMemento sm = (StatusMemento)mementoInterface;
        this.bloodVolume = sm.bloodVolume;
        this.magicPoint = sm.magicPoint;
    }
    
    private class StatusMemento implements MementoInterface{
        private Integer bloodVolume;
        private Integer magicPoint;
        StatusMemento(Integer bloodVolume,Integer magicPoint){
            this.bloodVolume = bloodVolume;
            this.magicPoint = magicPoint;
        }
    }
}

  接口标识类,方便咱们在类外部访问其局部内部类

package memento;

public interface MementoInterface {

}

  管理者类

package memento;

public class MementoManager {

    private MementoInterface memento;

    public MementoInterface getMemento() {
        return memento;
    }

    public void setMemento(MementoInterface memento) {
        this.memento = memento;
    }
    
    
}

  测试代码及执行结果

  备忘录模式的优势

  一、有时一些发起人对象的内部信息必须保存在发起人对象之外的地方,可是必需要由发起人对象本身读取,这时,使用备忘录模式能够把复杂的发起人内部信息对其余的对象屏蔽起来,从而能够恰当地保持封装的边界。

  二、本模式简化了发起人类。发起人再也不须要管理和保存其内部状态的一个个版本,客户端能够自行管理他们所须要的这些状态的版本。

  三、当发起人角色的状态改变的时候,有可能这个状态无效,这时候就能够使用暂时存储起来的备忘录将状态复原。

  备忘录模式的缺点:

  一、若是发起人角色的状态须要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象会很昂贵。

  二、当负责人角色将一个备忘录 存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而没法提醒用户一个操做是否很昂贵。

  三、当发起人角色的状态改变的时候,有可能这个协议无效。若是状态改变的成功率不高的话,不如采起“假如”协议模式。

相关文章
相关标签/搜索