004-行为型-07-备忘录模式(Memento)

一、概述

  又叫做快照模式(Snapshot Pattern)或Token模式

  保存对象的内部状态,并在需要的时候(undo/rollback)恢复对象以前的状态。

  意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

  主要解决:所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。

  备忘录模式和状态模式:备忘录模式是对象表示状态,状态模式是用类来表示状态。

1.1、适用场景

  1、需要保存/恢复数据的相关状态场景。 2、提供一个可回滚的操作。

  (1)一个类需要保存它的对象的状态(相当于Originator角色)
  (2)设计一个类,该类只是用来保存上述对象的状态(相当于Memento角色)
  (3)需要的时候,Caretaker角色要求Originator返回一个Memento并加以保存
  (4)undo或rollback操作时,通过Caretaker保存的Memento恢复Originator对象的状态

1.2、优缺点

  优点: 1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。 2、实现了信息的封装,使得用户不需要关心状态的保存细节。

  缺点:消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

1.3、类图角色及其职责

  

  1、Originator(原生者):需要被保存状态以便恢复的那个对象,负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator可以根据需要决定Memento存储自己的哪些内部状态。

  2、Memento(备忘录):该对象由Originator创建,主要负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator却可看到备忘录的宽接口,允许它访问返回到先前状

态所需要的所有数据。

  3、Caretaker(管理者):负责在适当的时间保存/恢复Originator对象的状态,负责备忘录Memento,不能对Memento的内容进行访问或者操作。

1.4、演进过程

首先,新建一个Person类,他就是Originator(原生者)

/*
 * Originator(原生者)
 */
public class Person {
    /*
     * 姓名,年龄,性别就是结构图中的state,状态属性
     */
    //姓名
    private String name;
    //年龄
    private int age;
    //性别
    private String sex;

    public Person() {
        super();
    }

    public Person(String name, int age, String sex) {
        super();
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public void display() {
        System.out.println("name:" + name + ",sex:" + sex + ",age:" + age);
    }

    //创建一个备份
    public Memento createMemento() {
        return new Memento(name, age, sex);
    }

    //恢复一个备份
    public void setMemento(Memento memento) {
        this.name = memento.getName();
        this.age = memento.getAge();
        this.sex = memento.getSex();
    }
}

接着,创建一个Memento(备忘录),他和Originator的基本结构是一样的

/*
 * Memento(备忘录)
 */
public class Memento {
    //姓名
    private String name;
    //年龄
    private int age;
    //性别
    private String sex;

    public Memento() {
        super();
    }

    public Memento(String name, int age, String sex) {
        super();
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

创建管理者Caretaker(管理者)角色

/*
 * Caretaker(管理者)
 */
public class Caretaker {
    //持有一个对Memento的引用
    private Memento memento;

    public Memento getMemento() {
        return memento;
    }

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

测试

    @Test
    public void test() {
        Person person = new Person("小明",18,"男");
        //打印
        person.display();

        //创建一个管理者
        Caretaker caretaker = new Caretaker();

        //创建一个备份
//        Memento memento = person.createMemento();
        caretaker.setMemento(person.createMemento());

        person.setName("小红");
        person.setAge(17);
        person.setSex("女");
        //打印
        person.display();

        //备份还原
        person.setMemento(caretaker.getMemento());
        //打印
        person.display();
    }

输出

name:小明,sex:男,age:18
name:小红,sex:女,age:17
name:小明,sex:男,age:18

二、扩展

2.1、spring

org.springframework.binding.message.StateManageableMessageContext

数据库的事务管理。

猜你喜欢

转载自www.cnblogs.com/bjlhx/p/11573983.html