Skip to content

备忘录模式

ZHI-XINHUA edited this page Jan 11, 2019 · 1 revision

备忘录模式(Memento)

备忘录模式又叫快照模式,是对象的行为模式。 备忘录对象是一个用来存储另一个对象内部状态的快照(snapshot)的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉住,并外部化,存储起来;从而可以将来适合的时候把这个对象还原到存储起来的状态。

1、备忘录结构

备忘录模式涉及三个角色:备忘录角色(Memento)、发起人角色(Originator)和负责人角色(Caretaker)。

角色:

  • 备忘录角色(Memento):
    • 将发起人(Originator)对象的内部状态存储起来,备忘录可以根据发起人对象的判断来决定存储多少发起人对象
    • 备忘录可以保护其内容不被发起人对象自我的任何对象所读取。
  • 发起人角色(Originator):
    • 创建一个含有当前的内部状态的备忘录对象
    • 使用备忘录对象存储其内部状态
  • 负责人角色(Caretaker):负责保存备忘录对象,但是不检查备忘录对象的内容

2、demo

(1)Emp 发起人:1、可以进行备忘操作 2、进行数据恢复,恢复成制定备忘录对象的值

/**
 * 发起人(Originator)角色,如下责任:
 *  1、创建一个含有当前的内部状态的备忘录对象
 *  2、使用备忘录对象存储其内部状态
 */
public class Emp {
    private String ename;
    private int age;
    private double salary;

    /**
     * 进行备忘操作,并返回备忘录对象
     * @return
     */
    public EmpMemento memento(){
        return new EmpMemento(this);
    }

    /**
     * 进行数据恢复,恢复成制定备忘录对象的值
     * @param empMemento
     */
    public void recovery(EmpMemento empMemento){
        this.ename = empMemento.getEname();
        this.age = empMemento.getAge();
        this.salary = empMemento.getSalary();
    }



    public Emp(String ename, int age, double salary) {
        this.ename = ename;
        this.age = age;
        this.salary = salary;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

(2)EmpMemento 备忘录(Memento)角色:存储发起人状态

/**
 * 备忘录(Memento)角色,如下责任:
 * 1、将发起人(Originator)对象的内部状态存储起来,备忘录可以根据发起人对象的判断来决定存储多少发起人对象
 * 2、备忘录可以保护其内容不被发起人对象自我的任何对象所读取。
 */
public class EmpMemento {
    private String ename;
    private int age;
    private double salary;

    //将发起人(Originator)对象的内部状态存储起来
    public EmpMemento(Emp emp){
        this.ename = emp.getEname();
        this.age = emp.getAge();
        this.salary = emp.getSalary();
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}

(3)CareTaker负责人角色:负责保存备忘录对象

/**
 * 负责人(Caretaker)角色:负责保存备忘录对象,但是不检查备忘录对象的内容
 */
public class CareTaker {
    //备忘录对象
    private EmpMemento memento;

    //对个的时候可用集合,看实际情况而定
    //private List<EmpMemento> list = new ArrayList<EmpMemento>();

    public EmpMemento getMemento() {
        return memento;
    }

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

测试:

public static void main(String[] args) {
    //负责人,管理备忘录角色
    CareTaker careTaker = new CareTaker();

    Emp emp = new Emp("olay",20,6000);
    //进行备忘操作
    EmpMemento empMemento = emp.memento();

    //管理备忘录
    careTaker.setMemento(empMemento);

    System.out.println("第一次状态:Ename="+emp.getEname() +" Age="+emp.getAge() +" Salary="+emp.getSalary());

    //修改emp
    emp.setAge(21);
    emp.setSalary(8000);

    System.out.println("第二次状态:Ename="+emp.getEname() +" Age="+emp.getAge() +" Salary="+emp.getSalary());

    // 返回第一次的状态
    emp.recovery(empMemento);

    System.out.println("第三次状态:Ename="+emp.getEname() +" Age="+emp.getAge() +" Salary="+emp.getSalary());
}
第一次状态:Ename=olay Age=20 Salary=6000.0
第二次状态:Ename=olay Age=21 Salary=8000.0
第三次状态:Ename=olay Age=20 Salary=6000.0

3、开发中常见的应用场景:

  • 棋类游戏中的,悔棋
  • 普通软件中的,撤销操作
  • 数据库软件中的,事务管理中的,回滚操作
Clone this wiki locally