私は現在、運動としていくつかのデザインパターンを実装しようとしていますが、私はMementoパターンでちょっと固まっています。私の参照リソースはSourceMaking: Mementoです。Kotlinでメメントパターンを実装する方法
私は、この構造を実装する:
彼らの "チェックリスト"
- は「世話人」と「発信者」の役割を確認し、次ながら。
- Mementoクラスを作成し、発信者を友人として宣言します。
- Caretakerは発信者をいつチェックポイントするかを知っています。
- OriginatorはMementoを作成し、そのMementoにその状態をコピーします。
- ケアテイカーはを保有していますが、見ることはできませんメンメントです。
- 発信者を「ロールバック」するタイミングをCaretakerが認識しています。
- 発信者は、メメント内の保存済み状態を使用して自分自身を元に戻します。
手順5を実行することができません。 Originator
インスタンス内からフィールドを読み取れるが、それはCaretaker
に対して完全に不透明なMemento
オブジェクトを作成するにはどうすればよいですか?
:
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で実装できませんか?
もう1つの注意点:Mementoオブジェクトの不透明性の要件は実際にメメントパターンの口頭で受け入れられるプロパティか、SourceMakingはこの要件を思い付いたのですか?
ニース!それについて考えなかった。あなたはどのようにソリューションを評価しますか?これはあなたの意見でどうやってやるべきか、あるいは多分Javaの例から削除されているかもしれないが多分もっと良いKotlinコードでしょうか?私が言おうとしているのは、コードレビューであなたは親指をかけるか、空のインターフェースについて懐疑的だろうか? –
私の最初の懐疑主義は、おそらく、私は、何かが*何か*ではなく、何か*ではないことを記述するものとしてインターフェースを考えることが好きであるという事実に由来するでしょう。そして、この場合は主にタイプシステムをハックするために使用されますが、そうではありませんか? ここでスマートなお尻にしようとしていません。実用的な解決策であり、うまく動作します。おそらく実稼働環境で使用します。しかし、私はまだ学習し、言語をよりよく理解するための練習としてこれをやっているので、あなたの意見でこれを行うための "コットンの道"であるかどうかを知りたいだけです。 –
クラスのメンバーが特定のクラス(サブクラスとは別に、保護されていて、ここでは役に立たない)から見えるようにする可視性システム - Kotlinでは、パターンに必要な「友人」の可視性はありません。 Javaでは、囲むクラスがプライベートメンバーにアクセスできます。このパターンで十分です。実際に、私がインターフェイスで見るより大きな問題は、それが別のクラスによって実装できるということです。私は答えを編集しました。今は '抽象的な内部クラス 'なので、' Originator'の範囲外に継承することはできません。 – hotkey