gpt4 book ai didi

java - 纪念品模式的缺点

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:05:48 24 4
gpt4 key购买 nike

因此,这是一个典型的 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 方法)。

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

最佳答案

1) 请注意,Caretaker 应该负责保管 Mementos,不一定负责撤消/重做。如果您查看 Internet 上的各种实现(例如 here ),您会发现 Caretaker 没有 revert() 但通常类似于 getMemento() .所以负责撤消的类是其他人,它在 Caretaker 上调用 getMemento(),然后在 Subject 上调用 revert()

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

2) 在 Memento 模式中,一个类和它的 Memento 是紧密耦合的。实际上,只有类本身可以访问 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());
}
}

关于java - 纪念品模式的缺点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37626880/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com