我目前正尝试在Kotlin中实现一些设计模式,作为一个练习,我有点被“Memento”模式所困扰。我的参考资源是SourceMaking:纪念品。
我想实施这个结构:

同时遵循他们的“核对表”
我不能让第五步开始工作。如何使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实例读取State和State的私有字段,但是对于Caretaker,my 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中读取字段。
顺便说一句,这段代码与IntelliJ的“将Java”特性生成的代码几乎完全相同,该特性应用于我的Java代码(而且显然也不编译)。
那么,有什么明显的(或神奇的)我在这里错过了吗?也许是类图中显示的结构之外的其他东西?或者,这些精确的规范不能在Kotlin中实现吗?
另外一点是:对Memento对象的不透明要求实际上是Memento模式的一个口语化接受的属性,还是SourceMaking提出了这个要求?
发布于 2017-08-24 17:07:23
您可以为Memento定义一个公共父类,并为它定义一个私有继承类:
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
}
}实现类是private,在Originator之外,实例只能被看作是Memento (请参阅函数签名),这样就无法访问状态。
发布于 2017-08-24 16:58:28
您应该使用包级访问来定义Memento类属性。
https://stackoverflow.com/questions/45867006
复制相似问题