侧边栏壁纸
博主头像
孔子说JAVA博主等级

成功只是一只沦落在鸡窝里的鹰,成功永远属于自信且有毅力的人!

  • 累计撰写 292 篇文章
  • 累计创建 132 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

JAVA设计模式之备忘录模式

孔子说JAVA
2019-12-04 / 0 评论 / 0 点赞 / 79 阅读 / 2,951 字 / 正在检测是否收录...

1、备忘录模式(Memento)的定义

备忘录模式又叫做快照模式,指在不破坏封装性的前提下,获取到一个对象的内部状态,并在对象之外记录或保存这个状态。在有需要的时候可将该对象恢复到原先保存的状态。我们相当于把对象原始状态备份保留,所以叫备忘录模式。

  • 备忘录模式能记录一个对象的内部状态,当用户后悔时能撤销当前操作,使数据恢复到它原先的状态。其实很多应用软件都提供了这项功能,如 Word、记事本、Photoshop、Eclipse 等软件在编辑时按 Ctrl+Z 组合键时能撤销当前操作,使文档恢复到之前的状态;还有在 IE 中的后退键、数据库事务管理中的回滚操作、玩游戏时的中间结果存档功能、数据库与操作系统的备份操作、棋类游戏中的悔棋功能等都属于这类。

2、模式(Memento)优缺点

备忘录模式是一种对象行为型设计模式,其主要优缺点如下:

优点:

  1. 备忘录模式可以把发起人内部信息对象屏蔽起来,从而可以保持封装的边界。实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
  2. 提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
  3. 简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。(当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。)

缺点:

  1. 资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。
  2. 当发起者对象的状态改变的时候,有可能这个协议无效。如果状态改变的成功率达不到要求,可以考虑采取“假如”协议模式。

3、模式(Memento)适用环境

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

4、模式(Memento)的结构

image-1649384456386

备忘录模式的核心是设计备忘录类以及用于管理备忘录的管理者类,主要角色如下。

  1. 发起人(Originator)角色 :记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。Originator可根据需要决定Memento存储Originator的哪些内部状态。
  2. 备忘录(Memento)角色 :负责存储发起人的内部状态,并可防止Originator以外的其他对象访问备忘录Memento,在需要的时候提供这些内部状态给发起人。备忘录有两个接口,Caretaker只能看到备忘录的窄接口,它只能将备忘录传递给其他对象。Originator能够看到一个宽接口,允许它访问回到先前状态所需的所有数据。
  3. 管理者/负责人(Caretaker)角色 :对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行修改或检查。在负责人类中可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象,也无须知道对象的实现细节。

5、模式(Memento)的应用实例

备忘录在jsp+javabean的使用:在一系统中新增帐户时,在表单中需要填写用户名、密码、联系电话、地址等信息,如果有些字段没有填写或填写错误,当用户点击“提交”按钮时,需要在新增页面上保存用户输入的选项,并提示出错的选项。这就是利用JavaBean的scope="request"或scope="session"特性实现的,即是用备忘录模式实现的。

发起人代码 (创建一个含有当前的内部状态的备忘录对象;使用备忘录对象存储其内部状态。)

public class Person {
    private String name;
    private String sex;
    private int    age;
    // GETTER/SETTER方法省略
	
    public Person(String name, String sex, int age) {
        super();
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
    public Person() {}

    public void display() {
        System.out.println(" name "+name+" sex "+sex+" age "+age);
    }
	//创建一个备份
    public Memento createMemento(){  
        return new Memento(name, sex, age);  
    }  
    //恢复一个备份
    public void restoreMemento(Memento memento) {
    	this.name=memento.getName();
    	this.sex = memento.getSex();
    	this.age = memento.getAge();
	}
}

备忘录代码 (将发起人对象的内部状态存储起来;可以保护其内容不被发起人(Originator)对象之外的任何对象所读取。)

public class Memento {
    private String name;
    private String sex;
    private int    age;
    public Memento(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
	
    public Memento() {
        super();
    }
    // getter、setter略
}

管理者代码 (负责保存备忘录对象;不保存备忘录对象的内容。)

public class Caretaker {
    private Memento memento;
    // 如果需要存储多个备份,可以使用集合
    //private List<Memento> list = new ArrayList<Memento>();    
 
    public Memento getMemento() {
        return memento;
    }
 
    public void setMemento(Memento memento) {
        this.memento = memento;
    }
}

测试代码

public class Mainclass {
    public static void main(String[] args) {
        Person person = new Person("zhangsan","nan",20);
        //Memento memento = person.createMemento();
        Caretaker caretaker = new Caretaker();
        caretaker.setMemento(person.createMemento());
		
        person.display();
		
        person.setName("lisi");
        person.setSex("nv");
        person.setAge(23);
		
        person.display();
		
        person.restoreMemento(caretaker.getMemento());
        person.display();
    }
}
0

评论区