java设计模式-备忘录模式

文章转自:汤高的 Java设计模式(十九)—-备忘录模式他的这个文章整理的比较齐全,最重要是知其意。

参考:
JAVA设计模式之:备忘录模式
Java设计模式20-备忘录模式

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

比如说,我们正在做100个题目,然后做到一半就不想做了,这个时候我们可以把做到哪一题保存起来,下次接着做。

设计模式设计到三个角色:
Memento:
备忘录,负责存储原发者状态的对象。
Caretaker:
负责人,负责管理保存备忘录的对象。
Originator:
原发者,负责创建一个备忘录来记录当前对象的内部状态,并可使用备忘录恢复内部状态。

以一个写作业的案例来写代码

定义一个发起者,内部定义备忘录

package com.madman.base.designMode.memento;

import java.text.MessageFormat;

public class Originator{
    /**
     * 定义一个数字用来表达做到哪一题了
     */
    public int num;

    public int getNum() {
        return num;
    }

    /**
     * 创建人:madman
     * 创建时间:date()
     *
     * @param num
     */
    public void setNum(int num) {
        this.num = num;
    }

    /**
     * 创建备忘录
     *
     * @return
     */
    public Memento createMemento() {
        return new Memento(this.num);
    }

    /**
     * 恢复备忘录
     *
     * @param me
     */
    public void restoreMemento(Memento me) {
        this.num = me.num;
    }

    /**
     * 查看做到哪一题了
     */
    public void doNum() {
        System.out.println(MessageFormat.format("当前做到第{0}题目了", String.valueOf(num)));
    }

}

定义一个备忘录,备忘录的属性就是发起者需要保存的属性

package com.madman.base.designMode.memento;

/**
 * 创建备忘录对象
 * 这个对象的定义哪些属性 就需要看Originator需要备份哪些属性了
 * 这里还是定义num记录做到哪一题了
 * <p>
 * 直接使用构造方法进行参数赋值了
 */
public class Memento{
    public int num;

    public Memento(int num) {
        this.num = num;
    }

    public Memento() {
    }

    public int getNum() {
        return num;
    }

    /**
     * 创建人:madman
     * 创建时间:date()
     *
     * @param num
     */
    public void setNum(int num) {
        this.num = num;
    }
}

Caretaker创建一个管理备忘录的保存和恢复
这里的比较简单就是放在内存里面,实际使用应该不会这么潦草。

package com.madman.base.designMode.memento;

/**
 * 负责人对象,负责保存和恢复备忘录
 * 内部需要定义备忘录属性
 */
public class Caretaker{
    Memento me;

    public Memento getMe() {
        return me;
    }

    public void saveMemento() {
        /**
         * 一般而言保存备忘录一般不会放在内里里面
         * 写在其他地方的
         */
    }

    /**
     * 创建人:madman
     * 创建时间:date()
     *
     * @param me
     */
    public void setMe(Memento me) {
        this.me = me;
    }
}

Client测试,看下是否恢复到原始状态了

package com.madman.base.designMode.memento;

public class Client{

    public static void main(String[] args) {
        Caretaker caretaker = new Caretaker();
        Memento me = new Memento();
        Originator originator = new Originator();
        originator.setNum(1);
        originator.doNum();
        //创建备忘录
        Memento memento = originator.createMemento();
        originator.setNum(10);
        originator.doNum();
        //还原备忘录的状态
        originator.restoreMemento(memento);
        originator.doNum();

    }
}

结果

当前做到第1题目了
当前做到第10题目了
当前做到第1题目了

在上述的例子中Memento对象是一个单独的类,并且提供set方法,那么我不就可以调用set方法修改值了,这看着不太好对吧….
要让方法不被调用,只能把方法设置成private的了,但是设置成private,那只能自己访问了,所有我们改成内部类试试..

我们修改下发起者的代码Originator2,大概是这样,这样在外面获取到Memento2 的时候就不能改变他的属性值了。

package com.madman.base.designMode.memento;

import java.text.MessageFormat;

public class Originator2{
    /**
     * 定义一个数字用来表达做到哪一题了
     */
    public int num;

    public int getNum() {
        return num;
    }

    /**
     * 创建人:madman
     * 创建时间:date()
     *
     * @param num
     */
    public void setNum(int num) {
        this.num = num;
    }

    /**
     * 创建备忘录
     *
     * @return
     */
    public Memento2 createMemento() {
        return new Memento2(this.num);
    }

    /**
     * 恢复备忘录
     *
     * @param me
     */
    public void restoreMemento(Memento me) {
        this.num = me.num;
    }

    /**
     * 查看做到哪一题了
     */
    public void doNum() {
        System.out.println(MessageFormat.format("当前做到第{0}题目了", String.valueOf(num)));
    }

    class Memento2{
        private int num;

        private Memento2(int num) {
            this.num = num;
        }

        private Memento2() {
        }

        private int getNum() {
            return num;
        }

        /**
         * 创建人:madman
         * 创建时间:date()
         *
         * @param num
         */
        private void setNum(int num) {
            this.num = num;
        }

    }
}

测试还是跟刚才一样的….
除了设置方法和属性为private之外,还可以使用空接口的形式
可参考:汤高的Java设计模式(十九)—-备忘录模式


备忘录模式从另外一个角度上可以理解直接备份整个类,可以把整个类序列化一下,保存到某个地方,当需要使用的时候直接读出来转成发起者就行,我觉得更方便点..主要还是看应用场景。


备忘录模式的优缺点
优点:

1、备忘录模式可以把发起人内部信息对象屏蔽起来,从而可以保持封装的边界。
2、简化了发起人类。当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。

缺点:

1、如果状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象比较昂贵。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值