Head First 设计模式系列之二----备忘录模式(java版)

申明:这几天无意中关注到备忘录模式,比较陌生回家一番参考书,只在附录里记录了该模式。后来在园子里有发现了有专门写设计模式的博客,并且写的也得牛逼。附上链接

http://www.cnblogs.com/java-my-life/tag/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/,真的写的很好。对于这个并不熟悉的模式,我也就参考他写的,并且以后肯定也会大量参考他写的。

  在儿时肯定上过游戏室吧,笔者当时西游记很火,我们四个小伙准备了好些钱,打算把游戏给打穿了。死了就接着投牌下去,接着刚才的剧情玩下去,到最后钱完了,四个人还是没有打穿。其实这里就包含着备忘录模式,死了以后记住你当前的状态,钱投下去了,恢复到当前状态接着玩,而不是从第一关苦逼开始。

一、定义和类图

备忘录对象是一人用来存储加外一个对象内部状态的快照对象。备忘录模式的用意是在不破坏封装条件下,将一个对象的状态捕捉信,并且外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常与命令模式和迭代模式一同使用(这个真没试用)。

Originator(发起人角色)、Memento(备忘录角色)、Caretaker(负责人角色)

形象说:土豪把钱装进箱子存进银行

二、代码实现

Originator类

package design.a.memento;
/**
 * 发起人角色
 * @author team
 *
 */
public class Originator {
    private String state;
    
    //创建备忘录角色
    public Memento createMemennto() {
        return new Memento(state);
    }
    
    //恢复到某个备忘录对象记录的角色
    public void restoreMemento(Memento memento) {
        this.setState(memento.getState());
    }
    
    public String getState() {
        return state;
    }
    
    public void setState(String state) {
        this.state = state;
        System.out.println("当前状态:" + this.state);
    }
}

Memento类:

package design.a.memento;
/**
 * 备忘录角色
 * 
 * @author team
 * 
 */
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;
    }
    
}

Caretaker类

package design.a.memento;
/**
 * 负责人角色
 * @author team
 *
 */
public class Caretaker {
    private Memento memento;
    
    public void saveMemento(Memento memento) {
        this.memento = memento;
    }
    
    public Memento retrieveMemento() {
        return this.memento;
    }
    
}

MainTest类

package design.a.memento;
public class MainTest {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();
        //设置初始状态
        originator.setState("off");
        //创建备忘录对象(已经存了状态),并把这个备忘录对象存起来
        caretaker.saveMemento(originator.createMemennto());
        //更改状态
        originator.setState("on");
        //恢复状态
        originator.restoreMemento(caretaker.retrieveMemento());
    }
}

运行结果:

当前状态:off
当前状态:on
当前状态:off

认真的人会想到这两个问题:1.为什么创建的备忘录对象还要保存到负责人手里。这个负责人其实就是负责管理这个备忘录对象的,假如后面要求说恢得到某个状态,这时就需要这个负责人来统一管理了。(土豪没空保管钱装进箱子,请了个银行帮他保管,而不是放在家里自己管)

2.从上面的代码实现你会发现这个备忘录对象是对发起人和负责人都透明的,这是多么危险啊。(你装进箱子多少钱,让帮你保管钱的人知道了,说不定就会起非心,要是能够让帮你保管钱的人连里面装的是什么那多么好啊,就给他个箱子,你来保管吧)这个在java里面就可以用到接口和内部类来实现。

将Memento设成Originator类的内部类,从而将Memento对象封装在Originator里面;在外部提供一个标识接口MementoIF给Caretaker以及其他对象。

三、代码实现plus

Originator类

package design.a.mementoPlus;
/**
 * 
 * @author team
 *
 */
public class Originator {
    private String state;
    
    public void setState(String state) {
        this.state = state;
        System.out.println("当前状态:" + this.state);
    }
    
    public String getState() {
        return this.state;
    }
    
    public MementoIF createMemento() {
        return new Memento(state);
    }
    
    public void restoreMemento(MementoIF memento) {
        this.setState(((Memento)memento).getState());
    }
    
    class Memento implements MementoIF {
        private String state;
        
        private Memento(String state) {
            this.state = state;
        }
        public String getState() {
            return this.state;
        }
        
        public void setState(String state) {
            this.state = state;
        }
    }
}

MementoIF接口

package design.a.mementoPlus;
/**
 *
 * @author team
 *
 */
public interface MementoIF {

}

Caretaker类

package design.a.mementoPlus;
/**
 * 
 * @author team
 *
 */
public class Caretaker {
    private MementoIF memento;
    //备忘录对象获取
    public MementoIF retrieveMemento() {
        return memento;
    }
    //备忘录赋值
    public void saveMemento(MementoIF memento){
        this.memento = memento;
    }
}

MainTest类

package design.a.mementoPlus;
/**
 * 
 * @author team
 *
 */
public class MainTest {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();
        //设置初始状态
        originator.setState("off");
        //创建备忘录对象(已经存了状态),并把这个备忘录对象存起来
        caretaker.saveMemento(originator.createMemento());
        //更改状态
        originator.setState("no");
        //恢复状态
        originator.restoreMemento(caretaker.retrieveMemento());
        
    }
}

运行结果:

当前状态:off
当前状态:no
当前状态:off

问题来了:就像上面说的问题1负责人哪能就干这么简单的事,(土豪钱多要保存多个箱子,让他随时取出他想要的箱子)我们就需要存储多个状态

备忘录模式可以将发起人对象的状态存储到备忘录对象里面,备忘录模式可以将发起人对象恢复到备忘录对象所存储的某一个检查点上

四、代码实现plus++

Originator类

package design.a.mementoPlus2;
import java.util.ArrayList;
import java.util.List;
/**
 * 
 * @author team
 *
 */
public class Originator {
    private List<String> states;
    
    public Originator() {
        states = new ArrayList<String>();
    }
    //创建备忘录
    public Memento createMemento() {
        return new Memento(states);
    }
    //恢复到备忘录记录的状态
    public void restoreMemento(Memento memento) {
        states = memento.getStates();
    }
    //状态赋值
    public void setState(String state) {
        states.add(state);
    }
    //打印状态
    public void printStates() {
        for(String state : states) {
            System.out.println(state);
        }
    }
}

Memento类

package design.a.mementoPlus2;
import java.util.ArrayList;
import java.util.List;
/**
 * 
 * @author team
 *
 */
public class Memento {
    private List<String> states;
    
    public Memento(List<String> states) {
        this.states = new ArrayList<String>(states);
    }

    public List<String> getStates() {
        return states;
    }

}

Caretaker类

package design.a.mementoPlus2;
import java.util.ArrayList;
import java.util.List;
/**
 * 
 * @author team
 *
 */
public class Caretaker {
    private Originator originator;
    
    private List<Memento> mementos = new ArrayList<Memento>();
    
    public Caretaker(Originator originator) {
        this.originator = originator;
    }
    //创建备忘录
    public void createMemento() {
        Memento memento = originator.createMemento();
        mementos.add(memento);
    }
    //恢复到备忘录记录的状态
    public void restoreMemento(int index) {
        Memento memento = mementos.get(index);
        originator.restoreMemento(memento);
    }
    
}

MainTest类

package design.a.mementoPlus2;
/**
 * 
 * @author team
 *
 */
public class MainTest {
    public static void main(String[] args) {
        Originator originator = new Originator();

        Caretaker caretaker = new Caretaker(originator);

        originator.setState("state one");

        caretaker.createMemento();

        originator.setState("state two");

        caretaker.createMemento();

        originator.setState("state three");

        caretaker.createMemento();
        
        originator.setState("state four");

        caretaker.createMemento();
        
        System.out.println("打印当前所有状态");
        originator.printStates();
        
        caretaker.restoreMemento(2);
        
        System.out.println("打印恢复后的所有状态");
        originator.printStates();
        
        
    }
}

注意刚才写Memento备忘录时开始:this.states = states;造成运行一直出错,states是个List是对象引用,所以return new Memento(states);每次产生的Memento

里面的states都是指向同一个的。应该写成this.states = new ArrayList<String>(states);

运行结果

打印当前所有状态
state one
state two
state three
state four
打印恢复后的所有状态
state one
state two
state three

所谓“自述历史”模式(History-On-Self Pattern)实际上就是备忘录模式的一个变种。在备忘录模式中,发起人(Originator)角色、负责人(Caretaker)角色和备忘录 (Memento)角色都是独立的角色。虽然在实现上备忘录类可以成为发起人类的内部成员类,但是备忘录类仍然保持作为一个角色的独立意义。在“自述历 史”模式里面,发起人角色自己兼任负责人角色。

五、代码实现plus++++

MementoIF接口

package design.a.mementoPlus3;
/**
 * 
 * @author team
 *
 */
public interface MementoIF {

}

Originator类

package design.a.mementoPlus3;
/**
 * 
 * @author team
 * 
 */
public class Originator {
    public String state;

    public void changeState(String state) {
        this.state = state;
        System.out.println("状态改为:" + state);
    }

    public Memento createMemento() {
        return new Memento(this);
    }

    public void restoreMemento(MementoIF memento) {
        Memento memento2 = (Memento) memento;
        changeState(memento2.state);
    }

    private class Memento implements MementoIF {
        private String state;

        private Memento(Originator originator) {
            this.state = originator.state;
        }
    }
}

MainTest类

package design.a.mementoPlus3;

public class MainTest {
    public static void main(String[] args) {
        Originator originator = new Originator();
        
        originator.changeState("state one");
        
        MementoIF memento = originator.createMemento();
        
        originator.changeState("state two");
        
        originator.restoreMemento(memento);
    }
}

运行结果:

状态改为:state one
状态改为:state two
状态改为:state one

由于在实际中还没有应用过备忘录模式,后面可能还会再写一篇应用的。

 

posted @ 2014-11-09 02:44  我是诗爷  阅读(1006)  评论(0编辑  收藏  举报