如何在Kotlin中实现纪念模式

我目前正在尝试在Kotlin中实现一些设计模式作为练习,而且我有点卡住了“纪念品”模式。 我的参考资源是SourceMaking:Memento 。

我想要实现这个结构:

“纪念品”设计模式的类图

当按照他们的“清单”

  1. 确定“看管人”和“鼻祖”的角色。
  2. 创建一个纪念品课,并宣布发起人的朋友。
  3. 看守人知道什么时候“检查点”的鼻祖。
  4. 发起人创建一个纪念品,并将其状态复制到该纪念品。
  5. 看守者坚持(但不能偷看)纪念品。
  6. 看守人知道什么时候“回滚”发起人。
  7. 发起人使用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); } } 

因为它们是内部类,我可以从我的Originator实例中读取MementoState的私有字段,但是对于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的'Convert Java to Kotlin'功能生成的代码几乎完全一样(显然它也不能编译)。

那么有什么明显的(或神奇的)我在这里失踪? 也许是类图中显示的结构以外的东西? 或者这些确切的规格是不是可以在Kotlin中实现?

而另一个说明:对于纪念物件的不透明性的要求,实际上是否是纪念图案的通俗接受的属性,还是SourceMaking提出这个要求?

您可以为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 (见函数签名),这样状态将不可访问。

您应该使用包级访问来定义您的Memento类属性。

Interesting Posts