行为型设计模式之备忘录模式

Posted 丨Jack_Chen丨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了行为型设计模式之备忘录模式相关的知识,希望对你有一定的参考价值。

@TOC

备忘录模式

应用场景

1.需要保存历史快照的场景

2.希望在对象之外保存状态,且除了自己其他类对象无法访问状态保存具体内容

应用场景举例:代码版本控制,游戏存档功能,数据库的事务管理等

优缺点

优点:

1.简化发起人实体类Originator职责,隔离状态存储与获取,实现了信息的封装,客户端无需关心状态的保存细节

2.提供状态回滚功能:给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。

缺点:

1.消耗资源:如果需要保存的状态过多时,每一次保存都会消耗很多内存。

主要角色

备忘录模式主要包含三种角色:

1.发起人角色(Originator)

2.备忘录角色(Memento)

3.备忘录管理员角色(Caretaker)

备忘录模式的基本使用

创建发备忘录角色

@Data
public class Memento 
    private String state;

    public Memento(String state)
        this.state = state;
    

创建发起人角色

@Data
public class Originator 
    /**
     * 内部状态
     */
    private String state;

    /**
     * 创建一个备忘录
     *
     * @return
     */
    public Memento createMemento() 
        return new Memento(this.state);
    

    /**
     * 从备忘录恢复
     *
     * @param memento
     */
    public void restoreMemento(Memento memento) 
        this.setState(memento.getState());
    

创建备忘录管理员角色

public class Caretaker 
    private Memento memento;

    public Memento getMemento() 
        return this.memento;
    
    public void storeMemento(Memento memento) 
        this.memento = memento;
    

客户端执行

    public static void main(String[] args) 
        // 创建发起人角色
        Originator originator = new Originator();
        // 创建备忘录管理员
        Caretaker caretaker = new Caretaker();
        // 设置存储状态
        originator.setState("A");
        // 存储发起人创建的备忘录
        caretaker.storeMemento(originator.createMemento());
        System.out.println("设置存储状态:" + originator.getState());

        // 设置存储状态
        originator.setState("B");
        System.out.println("更新存储状态:" + originator.getState());

        // 备忘录进行回滚
        originator.restoreMemento(caretaker.getMemento());
        System.out.println("回滚到设置的状态:" + originator.getState());
    
设置存储状态:A
更新存储状态:B
回滚到设置的状态:A

使用备忘录模式实现代码版本控制

创建发备忘录角色

@Data
@ToString
public class CodeMemento 
    /**
     * 提交内容
     */
    private String content;
    /**
     * 提交备注
     */
    private String remark;

    public CodeMemento(String content, String remark) 
        this.content = content;
        this.remark = remark;
    

创建发起人角色

@Data
@ToString
public class GitOriginator 
    /**
     * 提交内容
     */
    private String content;
    /**
     * 提交备注
     */
    private String remark;

    public GitOriginator(String content, String remark) 
        this.content = content;
        this.remark = remark;
    

    /**
     * 提交代码
     *
     * @return
     */
    public CodeMemento saveToMemento() 
        CodeMemento codeMemento = new CodeMemento(this.content, this.remark);
        return codeMemento;
    

    /**
     * 恢复代码
     *
     * @param codeMemento
     */
    public void undoFromMemento(CodeMemento codeMemento) 
        this.content = codeMemento.getContent();
        this.remark = codeMemento.getRemark();
    

创建备忘录管理员角色

public class GitCaretaker 
    /**
     * 使用栈来存储备忘录,最新的备忘录排在栈顶
     */
    private final Stack<CodeMemento> STACK = new Stack<CodeMemento>();

    public CodeMemento getMemento()
        // 移除栈顶的备忘录
        CodeMemento codeMemento = STACK.pop();
        return codeMemento;
    

    public void addMemento(CodeMemento codeMemento)
        // 将备忘录压入栈顶
        STACK.push(codeMemento);
    

客户端执行

    public static void main(String[] args) 
        System.out.println("--------------------第一次创建代码--------------------------------");
        // 创建一个备忘录管理者
        GitCaretaker gitCaretaker = new GitCaretaker();
        // 创建一个备忘录发起人
        GitOriginator gitOriginator = new GitOriginator("write code 1", "第一次提交代码备注");
        // 创建一个备忘录
        CodeMemento codeMemento = gitOriginator.saveToMemento();
        // 将备忘录压入栈顶
        gitCaretaker.addMemento(codeMemento);
        System.out.println("第一次提交代码完成。代码:" + gitOriginator.getContent() + " 备注:" + gitOriginator.getRemark());

        System.out.println("--------------------第二次修改代码--------------------------------");
        gitOriginator.setContent("write code 2");
        gitOriginator.setRemark("第二次提交代码备注");
        codeMemento = gitOriginator.saveToMemento();
        gitCaretaker.addMemento(codeMemento);
        System.out.println("第二次提交代码完成。代码:" + gitOriginator.getContent() + " 备注:" + gitOriginator.getRemark());

        System.out.println("--------------------第三次修改代码--------------------------------");
        gitOriginator.setContent("write code 3");
        System.out.println("第三次修改代码。代码:" + gitOriginator.getContent());

        System.out.println("--------------------在第三次修改代码基础上回退到第二次提交--------------------------------");
        codeMemento = gitCaretaker.getMemento();
        gitOriginator.undoFromMemento(codeMemento);
        System.out.println("回退到第二次提交完成。代码:" + gitOriginator.getContent() + " 备注:" + gitOriginator.getRemark());

        System.out.println("--------------------在第二次修改代码基础上回退到第一次提交--------------------------------");
        codeMemento = gitCaretaker.getMemento();
        gitOriginator.undoFromMemento(codeMemento);
        System.out.println("回退到第一次提交完成。代码:" + gitOriginator.getContent() + " 备注:" + gitOriginator.getRemark());
    
--------------------第一次创建代码--------------------------------
第一次提交代码完成。代码:write code 1 备注:第一次提交代码备注
--------------------第二次修改代码--------------------------------
第二次提交代码完成。代码:write code 2 备注:第二次提交代码备注
--------------------第三次修改代码--------------------------------
第三次修改代码。代码:write code 3
--------------------在第三次修改代码基础上回退到第二次提交--------------------------------
回退到第二次提交完成。代码:write code 2 备注:第二次提交代码备注
--------------------在第二次修改代码基础上回退到第一次提交--------------------------------
回退到第一次提交完成。代码:write code 1 备注:第一次提交代码备注

以上是关于行为型设计模式之备忘录模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式行为型备忘录模式

设计模式行为型备忘录模式

设计模式行为型备忘录模式

4 行为型模式之- 备忘录模式

22行为型模式之备忘录模式

行为型模式之备忘录模式