欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Java 行为型设计模式 VI】备忘录模式详解

程序员文章站 2022-02-06 11:36:42
...

 
【Java 行为型设计模式 VI】备忘录模式详解愿你如阳光,明媚不忧伤。

 


12. 备忘录模式

Memento 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。如 Word、记事本、Photoshop、Eclipse 等软件在编辑时按 Ctrl+Z 组合键时能撤销当前操作,使文档恢复到之前的状态。

备忘录模式优点和缺点

  • 优点
  1. 提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
  2. 实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
  3. 简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。
  • 缺点
  1. 资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。

备忘录模式的应用场景

  1. 需要保存与恢复数据的场景,如玩游戏时的中间结果的存档功能。
  2. 需要提供一个可回滚操作的场景,如 Word、记事本、Photoshop,Eclipse 等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作。

备忘录模式模式的结构

备忘录模式的核心是设计备忘录类以及用于管理备忘录的管理者类。
1. 发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
2. 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
3. 管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
发起人Originator +setState(String state) : void +getState() : String +createMemento() : Memento +restoreMemento(Memento memento) : void 备忘录Memento -state:String +Memento(String state) +setState(String state) : void +getState() : String 管理者Caretaker -memento:Memento +setMemento(Memento memento) : void +getMemento() : Memento 访问类Client +main() : void Aggregate

备忘录模式的实现

package com.example.demo.controller;

public class MementoController {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();
        originator.setState("S0");
        System.out.println("初始状态:" + originator.getState());
        // 保存状态
        caretaker.setMemento(originator.createMemento());
        // 设置新的状态
        originator.setState("S1");
        System.out.println("新的状态:" + originator.getState());
        // 恢复状态
        originator.restoreMemento(caretaker.getMemento());
        System.out.println("恢复状态:" + originator.getState());
    }
}

// 备忘录
class Memento {
    private String state;

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

    public void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}

// 发起人
class Originator {
    private String state;

    public void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

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

    public void restoreMemento(Memento memento) {
        this.setState(memento.getState());
    }
}

// 管理者
class Caretaker {
    private Memento memento;

    public void setMemento(Memento memento) {
        this.memento = memento;
    }

    public Memento getMemento() {
        return memento;
    }
}
-----------------------------------------------------------------
・【运行结果】
	初始状态:S0
	新的状态:S1
	恢复状态:S0

备忘录模式的扩展

clone() 方法具有自备份功能,所以,如果让发起人实现 Cloneable 接口就有备份自己的功能,这时可以删除备忘录类。

  • 原型备忘录模式
发起人原型OriginatorPrototype -state:String +setState(String state) : void +getState() : String +createMemento() : OriginatorPrototype +restoreMemento(OriginatorPrototype opt) : void +clone() : OriginatorPrototype «Interface» 克隆接口Cloneable +clone() : Object 管理者原型CaretakerPrototype -opt:OriginatorPrototype +setMemento(OriginatorPrototype opt) : void +getMemento() : OriginatorPrototype 访问类Client +main() : void Relazition Aggregate
package com.example.demo.controller;

public class MementoController {
    public static void main(String[] args) throws CloneNotSupportedException {
        OriginatorPrototype opt = new OriginatorPrototype();
        CaretakerPrototype caretaker = new CaretakerPrototype();
        opt.setState("S0");
        System.out.println("初始状态:" + opt.getState());
        // 保存状态
        caretaker.setMemento(opt.createMemento());
        // 设置新的状态
        opt.setState("S1");
        System.out.println("新的状态:" + opt.getState());
        // 恢复状态
        opt.restoreMemento(caretaker.getMemento());
        System.out.println("恢复状态:" + opt.getState());
    }
}

/*// 备忘录
class Memento {
    private String state;

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

    public void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}*/

// 发起人
class OriginatorPrototype implements Cloneable{
    private String state;

    public void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

/*    public Memento createMemento() {
        return new Memento(state);
    }

    public void restoreMemento(Memento memento) {
        this.setState(memento.getState());
    } */

    public OriginatorPrototype createMemento() throws CloneNotSupportedException {
        return (OriginatorPrototype) this.clone();
    }

    public void restoreMemento(OriginatorPrototype opt) {
        this.setState(opt.getState());
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

// 管理者
class CaretakerPrototype {
    private OriginatorPrototype opt;

    public void setMemento(OriginatorPrototype opt) {
        this.opt = opt;
    }

    public OriginatorPrototype getMemento() {
        return opt;
    }
}
-----------------------------------------------------------------
・【运行结果】
	初始状态:S0
	新的状态:S1
	恢复状态:S0

 


【每日一面】

一句话归纳设计模式
分类 设计模式 简述 一句话归纳 目的 生活案例
创建型1 工厂模式 不同条件下创建不同实例 产品标准化,生产更高效 封装创建细节 实体工厂
创建型2 单例模式 保证一个类仅有一个实例,并且提供一个全局访问点 世上只有一个我 保证独一无二 CEO
创建型3 原型模式 通过拷贝原型创建新的对象 拔一根猴毛,吹出千万个 高效创建对象 克隆
创建型4 建造者模式 用来创建复杂的复合对象 高配中配和低配,想选哪配就哪配 开放个性配置步骤 选配
结构型1 代理模式 为其他对象提供一种代理以控制对这个对象的访问 没有资源没时间,得找别人来帮忙 增强职责,附加功能 媒婆
结构型2 外观模式 对外提供一个统一的接口用来访问子系统 打开一扇门,通向全世界 统一访问入口 前台
结构型3 装饰器模式 为对象添加新功能 他大舅他二舅都是他舅 灵活扩展、同宗同源 煎饼
结构型4 享元模式 使用对象池来减少重复对象的创建 优化资源配置,减少重复浪费 共享资源池 全国社保联网
结构型5 组合模式 将整体与局部(树形结构)进行递归组合,让客户端能够以一种的方式对其进行处理 人在一起叫团伙,心在一起叫团队 统一整体和个体 组织架构树
结构型6 适配器模式 将原来不兼容的两个类融合在一起 万能充电器 兼容转换 电源适配
结构型7 桥接模式 将两个能够独立变化的部分分离开来 约定优于配置 不允许用继承
行为型1 模板模式 定义一套流程模板,根据需要实现模板中的操作 流程全部标准化,需要微调请覆盖 逻辑复用 把大象装进冰箱
行为型2 策略模式 封装不同的算法,算法之间能互相替换 条条大道通罗马,具体哪条你来定 把选择权交给用户 选择支付方式
行为型3 责任链模式 拦截的类都实现统一接口,每个接收者都包含对下一个接收者的引用。将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止 各人自扫门前雪,莫管他们瓦上霜 解耦处理逻辑 踢皮球
行为型4 迭代器模式 提供一种方法顺序访问一个聚合对象中的各个元素 流水线上坐一天,每个包裹扫一遍 统一对集合的访问方式 逐个检票进站
行为型5 命令模式 将请求封装成命令,并记录下来,能够撤销与重做 运筹帷幄之中,决胜千里之外 解耦请求和处理 遥控器
行为型6 状态模式 根据不同的状态做出不同的行为 状态驱动行为,行为决定状态 绑定状态和行为 订单状态跟踪
行为型7 备忘录模式 保存对象的状态,在需要时进行恢复 失足不成千古恨,想重来时就重来 备份、后悔机制 草稿箱
行为型8 中介者模式 将对象之间的通信关联关系封装到一个中介类中单独处理,从而使其耦合松散 联系方式我给你,怎么搞定我不管 统一管理网状资源 朋友圈
行为型9 解释器模式 给定一个语言,定义它的语法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子 我想说”方言“,一切解释权都归我 实现特定语法解析 摩斯密码
行为型10 观察者模式 状态发生改变时通知观察者,一对多的关系 到点就通知我 解耦观察者与被观察者 闹钟
行为型11 访问者模式 稳定数据结构,定义新的操作行为 横看成岭侧成峰,远近高低各不同 解耦数据结构和数据操作 KPI考核
行为型12 委派模式 允许对象组合实现与继承相同的代码重用,负责任务的调用和分配 这个需求很简单,怎么实现我不管 只对结果负责 授权委托书