因此,这是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());
    }
}

我发现此模式的所有实现都或多或少等于上述模式。但是这种实现方式存在一些我不喜欢的问题:
  • 可以同时触发employee.revert()caretaker.revert(employee)。我只想有一个接入点。
  • 如果要更改EmployeeMemento,则还必须在Employee类中进行更改(因为revert方法)。

  • 有办法克服吗?
    还是我太在意,而这个细节不是那么重要?

    最佳答案

    1)请注意,看守员应该照顾持有Mementos,而不必照顾撤消/重做。如果查看Internet上的各种实现(例如here),您会看到Caretaker没有revert(),但通常带有getMemento()之类的东西。因此,负责Undoing的类是在Caretaker上调用getMemento(),然后在Subject上调用revert()的其他人。

    即使您希望Caretaker负责撤消操作,也请注意employee.revert()caretaker.revert()专门创建的一种方法,因为在此设计中,没有其他人可以访问Mementos。您可以降低其可见性,使其仅由看守人可见。 (如果这是C++,则可以使用friend轻松完成,但是在Java中,您必须具有创造力,并使用package可见性或其他方式。)

    2)在Memento模式中,一个类及其Memento是紧密耦合的。实际上,只有 class 本身可以访问Memento的内部,没有其他人可以看到Memento的组成。因此,对类的更改是否传播到其Memento都没有关系。

    再然后,如果您想隔离更改,则可以再次发挥创意。例如,除了提取Class和其Memento中的namephone外,您还可以提取另一个包含这些字段的类(以State的名称为例),然后在原始类及其Memento中使用此State。这样,当您更改类的状态时,只需要修改State即可。

    旁注:最好将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());
        }
    }
    

    10-05 22:39