努力保头发的打工人
努力保头发的打工人
发布于 2020-12-30 / 14 阅读 / 0 评论 / 0 点赞

备忘录模式

1 概述

定义 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到之前的状态。

备忘录模式就是提供一种对象的备份的模式,类图如下

备忘录模式类图.png

  • originator:发起人角色,负责定义那些属于备份范围,负责创建和恢复备忘录数据

  • memento:负责存储发起人内部的状态

  • caretaker:备忘录管理角色

2 应用场景

  • 需要保存和恢复数据的重要场所

  • 提供一个可回滚的操作

  • 需要监控一个副本场景

  • 数据库事务管理

3 注意事项

  • 备忘录声明周期:一般备忘录创建出来不会存储太久,要主动管理声明周期

  • 备忘录性能:不要频繁的建立备份的场景中使用,如for循环中,因为控制不了数量,创建新的对象要消耗资源的。

4 代码案例

创建一个需要备份的类

/**
 * @author chiangtaol
 * @date 2020-12-09
 * @describe 小明拥有特殊能力, 可以让自己身体回滚到某个时间的状态
 */
@Data
@NoArgsConstructor
public class XiaoMing implements Cloneable {
​
    /**
     * 身高
     */
    private Double height;
​
    /**
     * 体重
     */
    private Double weight;
​
    public XiaoMing(double height, double weight) {
        this.weight = weight;
        this.height = height;
    }
​
    /**
     * 创建备忘录
     */
    public Memo createMemo() {
        MemoImpl memo = new MemoImpl();
        BeanUtils.copyProperties(this, memo);
        return memo;
    }
​
    /**
     * 回到某个状态
     */
    public void restoreMemo(Memo memo) {
        BeanUtils.copyProperties(memo, this);
    }
​
​
    /**
     * 备忘录
     */
    @Data
    private class MemoImpl implements Memo {
        private Double height;
        private Double weight;
    }
}

创建管理备忘录的类和备忘录接口

/**
 * @author chiangtaol
 * @date 2020-12-09
 * @describe 备忘录接口,方便对实现类访问
 */
public interface Memo {
}
​
/**
 * @author chiangtaol
 * @date 2020-12-09
 * @describe 备忘录管理者
 */
public class Caretaker {
​
    /**
     * 存储备忘录,实际应用中可添加长度限制
     */
    private HashMap<String, Memo> memoMap = new HashMap<>();
​
    public Memo getMemo(String id) {
        return this.memoMap.get(id);
    }
​
    public void setMemoMap(String id, Memo memo) {
        this.memoMap.put(id, memo);
    }
​
}

下面是测试代码:

@Test
public void test(){
    XiaoMing xiaoMing = new XiaoMing(175,60);
    Caretaker caretaker = new Caretaker();
    // 备份当前状态
    caretaker.setMemoMap("1",xiaoMing.createMemo());
    // 经过一段时间
    xiaoMing.setHeight(176d);
    xiaoMing.setWeight(70d);
    caretaker.setMemoMap("2",xiaoMing.createMemo());
    // 又经过一段时间
    xiaoMing.setHeight(177d);
    xiaoMing.setWeight(80d);
​
    System.out.println("现在的小明:"+xiaoMing.toString());
    xiaoMing.restoreMemo(caretaker.getMemo("1"));
    System.out.println("回到状态1的小明:"+xiaoMing.toString());
    xiaoMing.restoreMemo(caretaker.getMemo("2"));
    System.out.println("回到状态2的小明:"+xiaoMing.toString());
}
​
//结果如下:
//现在的小明:XiaoMing(height=177.0, weight=80.0)
//回到状态1的小明:XiaoMing(height=175.0, weight=60.0)
//回到状态2的小明:XiaoMing(height=176.0, weight=70.0)