如何在 Kotlin 中实现 Memento Pattern
How to implement Memento Pattern in Kotlin
我目前正在尝试在 Kotlin 中实现一些设计模式作为练习,但我有点受困于 'Memento' 模式。我的参考资源是SourceMaking: Memento.
我想实现这个结构:
在关注他们的同时 "Checklist"
- 确定“看管人”和“发起人”的角色。
- 创建一个纪念品class并声明发起者为好友。
- 管理员知道什么时候 "check point" 发起人。
- Originator 创建一个 Memento 并将其状态复制到该 Memento。
- Caretaker 拿着 (但无法窥视) 纪念品。
- 管理员知道什么时候 "roll back" 发起人。
- 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);
}
}
因为它们是内部 classes 我可以从我的 Originator
实例中读取 Memento
和 State
的私有字段,但是到 Caretaker
我的 Memento
实例是完全不透明的(只显示 Object
s 成员函数)。
现在我该如何在 Kotlin 中实现这个确切的行为?基本上我缺少读取内部 classes 的私有字段的功能。
我能想到的最接近的事情是:
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 的 'Convert Java to Kotlin' 功能生成的代码几乎完全相同(而且它显然也无法编译)。
那么我在这里缺少什么明显的(或神奇的)东西吗?可能不是 class 图中显示的结构?或者这些确切的规范不能在 Kotlin 中实现吗?
另外请注意:Memento 对象的不透明性要求实际上是通俗接受的 属性 Memento 模式还是 SourceMaking 提出了这个要求?
您应该定义具有包级访问权限的 Memento
class 属性。
您可以为 Memento
定义一个 public 父 class 并为其定义一个私有继承者 class:
class Originator {
/* irrelevant declarations skipped */
abstract inner class Memento
private inner class MementoImpl(val state: State) : Memento()
fun saveState(): Memento {
return MementoImpl(State(id, title, description))
}
fun restore(memento: Memento) {
memento as MementoImpl
id = memento.state.id
title = memento.state.title
description = memento.state.description
}
}
实现 class 是 private
,并且在 Originator
之外,实例只会被视为 Memento
(参见函数签名),因此状态将无法访问。
我目前正在尝试在 Kotlin 中实现一些设计模式作为练习,但我有点受困于 'Memento' 模式。我的参考资源是SourceMaking: Memento.
我想实现这个结构:
在关注他们的同时 "Checklist"
- 确定“看管人”和“发起人”的角色。
- 创建一个纪念品class并声明发起者为好友。
- 管理员知道什么时候 "check point" 发起人。
- Originator 创建一个 Memento 并将其状态复制到该 Memento。
- Caretaker 拿着 (但无法窥视) 纪念品。
- 管理员知道什么时候 "roll back" 发起人。
- 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);
}
}
因为它们是内部 classes 我可以从我的 Originator
实例中读取 Memento
和 State
的私有字段,但是到 Caretaker
我的 Memento
实例是完全不透明的(只显示 Object
s 成员函数)。
现在我该如何在 Kotlin 中实现这个确切的行为?基本上我缺少读取内部 classes 的私有字段的功能。
我能想到的最接近的事情是:
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 的 'Convert Java to Kotlin' 功能生成的代码几乎完全相同(而且它显然也无法编译)。
那么我在这里缺少什么明显的(或神奇的)东西吗?可能不是 class 图中显示的结构?或者这些确切的规范不能在 Kotlin 中实现吗?
另外请注意:Memento 对象的不透明性要求实际上是通俗接受的 属性 Memento 模式还是 SourceMaking 提出了这个要求?
您应该定义具有包级访问权限的 Memento
class 属性。
您可以为 Memento
定义一个 public 父 class 并为其定义一个私有继承者 class:
class Originator {
/* irrelevant declarations skipped */
abstract inner class Memento
private inner class MementoImpl(val state: State) : Memento()
fun saveState(): Memento {
return MementoImpl(State(id, title, description))
}
fun restore(memento: Memento) {
memento as MementoImpl
id = memento.state.id
title = memento.state.title
description = memento.state.description
}
}
实现 class 是 private
,并且在 Originator
之外,实例只会被视为 Memento
(参见函数签名),因此状态将无法访问。