如何在Kotlin中实现纪念模式
我目前正在尝试在Kotlin中实现一些设计模式作为练习,而且我有点卡住了“纪念品”模式。 我的参考资源是SourceMaking:Memento 。
我想要实现这个结构:
当按照他们的“清单”
- 确定“看管人”和“鼻祖”的角色。
- 创建一个纪念品课,并宣布发起人的朋友。
- 看守人知道什么时候“检查点”的鼻祖。
- 发起人创建一个纪念品,并将其状态复制到该纪念品。
- 看守者坚持(但不能偷看)纪念品。
- 看守人知道什么时候“回滚”发起人。
- 发起人使用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
实例中读取Memento
和State
的私有字段,但是对于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
类属性。