我目前正在尝试在 Kotlin 中实现一些设计模式作为练习,但我有点坚持使用“Memento”模式。我的参考资源是SourceMaking: Memento。
我想实现这个结构:
在遵循他们的“清单”时
- 确定“看守人”和“发起人”的角色。
- 创建一个 Memento 类并将创建者声明为朋友。
- 看守者知道何时“检查点”发起者。
- Originator 创建一个 Memento 并将其状态复制到该 Memento。
- 看守人抓住(但不能窥视)纪念品。
- 看守者知道何时“回滚”发起者。
- Originator 使用 Memento 中保存的状态恢复自身。
我无法让第 5 步工作。如何制作一个Memento
对象,其字段可以从Originator
实例内部读取,但对Caretaker
?
我已经在 Java 中成功实现了这一点,如下所示:
public class Originator {
private final int id;
private String title;
private String description;
public Originator(int id) {
this.id = id;
}
/* skipping title and description getter & setter */
public Memento saveState() {
return new Memento(new State(id, title, description));
}
public void restore(Memento memento) {
id = memento.state.id;
title = memento.state.title;
description = memento.state.description;
}
private class State {
private final int id;
private final String title;
private final String description;
public State(int id, String title, String description) {
this.id = id;
this.title = title;
this.description = description;
}
}
public class Memento {
private final State state;
public Memento(State state) {
this.state = state;
}
}
}
和一个看护人
public class Caretaker {
public Originator originator;
public Caretaker(@NotNull Originator originator) {
this.originator = originator;
}
public Originator.Memento save() {
return originator.saveState();
}
public void restore(@NotNull Originator.Memento memento) {
originator.restoreFromState(memento);
}
}
因为它们是内部类,所以我可以从我的实例中读取私有字段Memento
,但对于我的实例来说是完全不透明的(仅显示s 成员函数)。State
Originator
Caretaker
Memento
Object
现在我如何在 Kotlin 中实现这种确切的行为?基本上我错过了读取内部类私有字段的功能。
我能想到的最接近的事情是:
class Originator(id: Long) {
private var id: Long = id
var description: String = ""
var title: String = ""
fun saveState() = Memento(State(id, title, description))
fun restoreState(memento: Memento) {
id = memento.state.id // <-- cannot access 'state': it is private in 'Memento'
title = memento.state.title // <-- cannot access 'state': it is private in 'Memento'
description = memento.state.description // <-- cannot access 'state': it is private in 'Memento'
}
inner class State(private val id: Long,
private val title: String,
private val description: String)
inner class Memento(private val state: State)
}
这具有Memento
对我的实例完全不透明的预期效果Caretaker
,但我也无法从Originator
其中读取字段。
顺便说一句,这段代码与应用于我的 Java 代码的 IntelliJ 的“将 Java 转换为 Kotlin”功能生成的代码几乎完全相同(而且它显然也不能编译)。
那么我在这里遗漏了什么明显(或神奇)的东西吗?也许不是类图中显示的结构?或者这些确切的规范不能在 Kotlin 中实现吗?
另一个注意事项:Memento 对象的不透明性要求实际上是 Memento 模式的通俗接受的属性,还是 SourceMaking 提出了这个要求?