设计模式-备忘录模式(Memento)

概述

定义 : 保存对象的某个状态, 以便在适当的时候恢复对象

类型 : 行为型

适用场景

  • 保存及恢复数据相关业务场景
  • 如游戏存档, 操作撤销, 即想恢复到之前的状态

优点

  • 为用户提供一种可恢复机制
  • 存档信息的封装

缺点

  • 资源占用

模式角色

  • Memento(备忘录) :

    • 备忘录存储原发器对象的内部状态。原发器根据需要决定备忘录存储原发器的哪些内部状态。
    • 防止原发器以外的其他对象访问备忘录。备忘录实际上有两个接口,管理者(Caretaker)只能看到备忘录的窄接口 — 它只能将备忘录传递给其他对象。相反 , 原发器能够看到一个宽接口, 允许它访问返回到先前状态所需的所有数据。理想的情况是只允许生成本备忘录的那个原发器访问本备忘录的内部状态。
  • Originator(原发器) :

    • 原发器创建一个备忘录,用以记录当前时刻它的内部状态。
    • 使用备忘录恢复内部状态。
  • Caretaker(负责人/管理者) :

    • 负责保存好备忘录
    • 不能对备忘录的内容进行操作或检查

代码实现

场景

以编辑一篇文章为例, 每次编辑前, 都将编辑之前的状态保存一个副本, 执行撤销操作之后可以恢复到编辑前的状态, 可以多次撤销

UML类图

设计模式-备忘录模式(Memento)_第1张图片

代码

Memento(备忘录) :

/**
 * 备忘录
 * 作为备忘录不能进行修改属性, 所以这里只暴露了Getter方法
 * @author 七夜雪
 * @create 2018-11-24 16:15
 */
public class Memento {
    private String title;
    private String content;

    public Memento(String title, String content) {
        this.title = title;
        this.content = content;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }
}

Originator(原发器) :

/**
 * @author 七夜雪
 * @create 2018-11-24 16:11
 */
public class Originator {
    private String title;
    private String content;
    private final Caretaker caretaker = new Caretaker();

    public Originator(String title, String content) {
        caretaker.addMemento(new Memento(title, content));
        this.title = title;
        this.content = content;
    }

    /**
     * 修改文章
     * @param title
     * @param content
     */
    public void modify(String title, String content){
        this.title = title;
        this.content = content;
    }


    /**
     * 撤销修改
     */
    public void undo(){
        Memento bak = caretaker.undoMemento();
        if (bak == null) {
            return;
        }
        this.title = bak.getTitle();
        this.content = bak.getContent();
    }

    /**
     * 打印操作,辅助测试
     */
    public void print(){
        System.out.println("文章标题 : " + title);
        System.out.println("文章内容 : " + content);
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        caretaker.addMemento(new Memento(this.title, content));
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        caretaker.addMemento(new Memento(title, this.content));
        this.content = content;
    }
}

Caretaker(负责人/管理者) :

import java.util.Stack;

/**
 * 管理者/负责人
 *
 * @author 七夜雪
 * @create 2018-11-24 16:16
 */
public class Caretaker {
	// 使用栈保存备份, 保证每次恢复的都是最近的一个状态
	// 利用栈的特性, 先进后出, 后进先出
    public Stack<Memento> stack = new Stack<>();

    /**
     * 添加备份
     * @param memento
     */
    public void addMemento(Memento memento){
        stack.push(memento);
    }

    /**
     * 恢复备份
     * @param memento
     */
    public Memento undoMemento(){
        if (stack.empty()) {
            System.out.println("无备份");
            return null;
        }
        return stack.pop();
    }

}

测试代码 :

    public static void main(String[] args) {
        String title = "听雪楼";
        String content = "听雪楼中听雪落, 彼岸花开彼岸零";
        Originator originator = new Originator(title, content);
        originator.print();
        title = "魔渡众生";
        content = "当神已无能为力, 便是魔渡众生";
        originator.modify(title, content);
        System.out.println("---------------分隔符----------------");
        originator.print();
        originator.setTitle("听雪江湖");
        System.out.println("---------------分隔符----------------");
        originator.print();
        originator.undo();
        System.out.println("---------------分隔符----------------");
        originator.print();
        originator.undo();
        System.out.println("---------------分隔符----------------");
        originator.print();
    }

输出结果 :

文章标题 : 听雪楼
文章内容 : 听雪楼中听雪落, 彼岸花开彼岸零
---------------分隔符----------------
文章标题 : 魔渡众生
文章内容 : 当神已无能为力, 便是魔渡众生
---------------分隔符----------------
文章标题 : 听雪江湖
文章内容 : 当神已无能为力, 便是魔渡众生
---------------分隔符----------------
文章标题 : 魔渡众生
文章内容 : 当神已无能为力, 便是魔渡众生
---------------分隔符----------------
文章标题 : 听雪楼
文章内容 : 听雪楼中听雪落, 彼岸花开彼岸零

本文参考:
慕课网课程
四人帮<设计模式>

你可能感兴趣的:(设计模式,设计模式)