3

因此,这里是 Memento 模式的典型实现(跳过的 getter 和 setter)。

public class Employee {
    private String name;
    private String phone;

    public EmployeeMemento save() {
        return new EmployeeMemento(name, phone);
    }

    public void revert(EmployeeMemento memento) {
        this.name = memento.getName();
        this.phone = memento.getPhone();
    }
}


  public class EmployeeMemento {
        private final String name;
        private final String phone;

        public EmployeeMemento(String name, String phone) {
            this.name = name;
            this.phone = phone;
        }
    }

public class Caretaker {
    private Stack<EmployeeMemento> history;

    public Caretaker() {
        history = new Stack<>();
    }

    public void save(Employee employee) {
        history.push(employee.save());
    }

    public void revert(Employee employee) {
        employee.revert(history.pop());
    }
}

我发现的这种模式的所有实现都或多或少等于上面的那个。但是这种实现存在一些问题,我不喜欢:

  1. 可以同时触发employee.revert()caretaker.revert(employee)。我希望只有一个接入点。
  2. 如果我们想更改 EmployeeMemento,我们还必须在 Employee 类中进行更改(因为revert方法)。

有没有办法克服这个问题?又或者是我太注意了,这个细节没那么重要?

4

1 回答 1

4

1)请注意,看守人应该负责持有纪念品,不一定负责撤消/重做。如果您查看 Internet 上的各种实现(例如此处),您会发现 Caretaker 没有revert()但通常类似getMemento(). 所以负责 Undoing 的类是调用getMemento()Caretaker 然后调用revert()Subject 的其他人。

即使您希望 Caretaker 处理 Undoing,请注意这employee.revert()是一种专门为供 使用而创建的方法caretaker.revert(),因为在此设计中,没有其他人可以访问 Mementos。您可以将其可见性降低为仅由看守人可见。(如果这是 C++,使用 可以很容易地完成friend,但在 Java 中,您必须有创意并使用package可见性或其他方式。)

2)在备忘录模式中,一个类和它的备忘录是紧密耦合的。实际上,只有类本身可以访问 Memento 的内部结构,其他人不应该看到 Memento 是如何组成的。因此,对类的更改是否传播到其 Memento 并不重要。

然后再一次如果你想隔离变化,你可以再次发挥创造力。例如,您可以提取另一个包含这些字段的类(假设名称为 ),而不是在 Class 及其 Memento中复制nameand ,然后在原始类及其 Memento 中使用它。这样,当您更改类的状态时,您只需修改.phoneStateStateState

旁注:最好将 Memento 定义为 Subject 内的嵌套静态类。

所以我的设计,解决你的问题,应该是这样的:

public class Employee {
    private State state;

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

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

    public static class Memento {
        private final State state;

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

    public static class State {
        private String name;
        private String phone;
    }
}

public class Caretaker {
    private Stack<Employee.Memento> history;

    public Caretaker() {
        history = new Stack<>();
    }

    public void addMemento(Employee.Memento memento) {
        history.push(memento);
    }

    public Employee.Memento getMemento() {
        return history.pop();
    }
}

public class UndoHandler {
    Employee employee;
    Caretaker caretaker;

    public void snapshot() {
        caretaker.save(employee.save());
    }

    public void undo() {
        employee.revert(caretaker.getMemento());
    }
}
于 2016-06-04T15:29:05.523 回答