zoukankan      html  css  js  c++  java
  • 23种设计模式之备忘录模式

    备忘录模式的定义

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

    通俗的说, 就是记录下类的当前状态, 当需要的时候恢复

    类图如下:

    23种设计模式之备忘录模式

     

    其中各角色如下:

    1. Originator 发起人角色: 记录当前时刻的内部状态, 负责定义哪些属于备份范围的状态, 负责创建和恢复备忘录数据
    2. Memento 备忘录角色: 负责存储 发起人对象的内部状态, 在需要的时候提供发起人需要的内部状态
    3. Cartetaker 备忘录管理员角色: 对备忘录进行管理、保存和提供备忘录.

    发起人角色代码:

    23种设计模式之备忘录模式

     

    备忘录角色代码:

    23种设计模式之备忘录模式

     

    备忘录管理员角色代码:

    23种设计模式之备忘录模式

     

    场景类:

    23种设计模式之备忘录模式

     

    备忘录模式的应用

    备忘录模式的使用场景:

    1. 需要保存和恢复数据的相关状态场景
    2. 提供一个可回滚的操作
    3. 需要监控的副本场景中. 例如要监控一个对象的属性, 但是监控又不应该作为系统的主业务来调用, 即使出现监控不准也影响不大, 因此一般做法是备份一个主线程中的对象
    4. 数据库连接的事务管理就是用的备忘录模式

    备忘录模式的注意事项:

    1. 备忘录的生命期. 备忘录创建出来就要在"最近"的 代码中使用, 要主动管理它的生命周期,建立就要使用, 不适用就要立即删除其引用, 等待垃圾回收期对他的回收处理
    2. 备忘录的性能. 不要再频繁建立备份的场景中使用别忘路模式, 原因如下: 一是控制不了备忘录建立的对象数量. 二是大对象的建立是要消耗资源的, 系统的性能需要考虑.

    备忘录模式的扩展

    1.clone方式的备忘录

    通过 clone 获取当前对象的副本, 在需要的时候进行还原, 这样就不需要备忘录对象了, 当然也就不需要备忘录管理角色了, 修改后的代码如下:

    23种设计模式之备忘录模式

     

    程序精简了很多.

    2.多状态的备忘录模式

    当类的状态有很多个的时候, 将状态一个一个写当然不是一个好办法, 那样要写大量的代码, 还容易犯错误.

    使用 clone 方式是可以解决的, 下面使用数据技术来解决, 实现一个JavaBean对象的所有状态的备份和还原

    通过一个工具类, 将JavaBean对象的所有属性都保存到一个HashMap中.

    发起人角色代码:

    23种设计模式之备忘录模式

     

    工具类代码:

    23种设计模式之备忘录模式

     

    当然,有很多工具已经提供了, 比如Apache的工具集commons等

    备忘录代码:

    23种设计模式之备忘录模式

     

    备忘录管理员角色代码不变.

    这样, 不管有多少状态都没问题了

    3.多备份的备忘录

    有时需要有多份备份, 我们先来说一个名词, 检查点, 也就是在备份的时候做的戳记, 系统级的备份一般是时间戳, 我们愁绪的检查点呢?一般是一个有意义的字符串.

    我们只要把通用代码的备忘录管理员修改一下就可以了, 代码如下:

    23种设计模式之备忘录模式

     

    这时要注意内存溢出的问题, 以为备份一旦产生就装入内存, 没有任何销毁的一项, 这是很危险的.

    4.封装得更好一点

    有时, 我们要保证备份不能被篡改, 要保证其他人没有备忘录的阅读权限, 只能是发起人可读, 这怎么办呢?

    我们将备忘录设成发起人的内部类, 让备忘录的方法均为私有,这样,就只有发起人可以调用备忘录的方法了, 那备忘录管理者如何获取备忘录呢? 只要让备忘录实现一个外部的空接口即可.

    发起人代码如下:

    23种设计模式之备忘录模式

     

    内置类全都是private的访问权限, 除了发起人外,别人休想访问到, 与其他类的关联关系通过公共接口实现

    备忘录的空接口:

    23种设计模式之备忘录模式

     

    备忘录管理者:

    23种设计模式之备忘录模式

     

    在这里, 使用了一个新的设计方法: 双接口设计, 我们的一个类可以实现多个接口, 在系统设计时, 如果考虑对象的安全问题, 则可以提供两个接口, 一个是业务的正常接口, 实现必要的业务逻辑,叫做宽接口; 另外一个是一个空接口, 什么方法都没有, 其目的是提供给子系统外的模块访问, 比如容器对象,这个叫做窄接口, 由于窄接口中没有提供任何操纵数据的方法, 因此相对来说比较安全


    在设计的时候不要使用数据库的临时表作为缓存备份数据了, 虽然是一个简单的办法,但是它加大了数据库操作的频繁度, 把压力下放到数据库了, 最好的解决办法就是使用备忘录模式.

  • 相关阅读:
    python进阶之装饰器之3利用装饰器强制函数上的类型检查
    python进阶之装饰器之6.装饰器为被包装函数增加参数,如何实现装饰器对类进行打补丁或者说对类的功能进行扩充
    python进阶之装饰器之5把装饰器作用到类和静态方法上
    python进阶之装饰器之4在类中定义装饰器,将装饰器定义为类,两者的区别与联系
    AOP的使用
    使用Maven搭建SSM框架
    js判断字符串是否有重复
    纯js实现复制功能
    关于Log文本的操作
    jquery往textarea鼠标光标选中的地方插入值
  • 原文地址:https://www.cnblogs.com/hujingnb/p/10171595.html
Copyright © 2011-2022 走看看