#Memento
[目次]
当該パターンはある時点でのオブジェクトの状態を保存しておくのが目的?
プライベートメンバは基本的に外部からアクセスすることはできません。しかし、色々なソフトウェアでctrl(あるいはcommand)+zキーで1つ前の状態へ完璧に戻れるように、ある特定のオブジェクトの状態をまるっと保存しておきたいシチュエーションは多々あると思います。
そんな時に本パターンを用いると理解しています
##目的
カプセル化を破壊せずに、オブジェクトの内部状態を捉えて外面化しておき、オブジェクトを後にこの状態に戻すことができるようにする。
##構成要素
・Memento あるオブジェクトの状態を保存しておくクラス
・Originator ある時点での状態を保存しておきたいオブジェクト。mementoオブジェクトを生成し、元に戻すためにmementoオブジェクトを使う。
・Caretaker Mementoオブジェクトの保管庫
##実装
ゲームのセーブデータを作るような感じのサンプルプログラムを実装します。
###Memento あるオブジェクトの状態を保存しておくクラス
セーブデータクラス
任意の時点でのレベル、所持金、経験値のキャプチャを保存します。
package memento
class SaveData(val level: Int, val gold: Int, val point: Int) {
fun show() {
println("レベル:$level 所持金:$gold 経験値:$point")
}
}
###Originator ある時点での状態を保存しておきたいオブジェクト。mementoオブジェクトを生成し、元に戻すためにmementoオブジェクトを使う。
現在プレイ中の情報
package memento
class Game(private var level: Int, private var gold: Int, private var point: Int) {
fun show() {
println("レベル:$level 所持金:$gold 経験値:$point")
}
/**
* 敵を倒した
*/
fun enemyDown(enemyLevel: Int) {
point += enemyLevel
if (point >= 10) {
level += point / 10
point %= 10
}
gold += enemyLevel
}
/**
* 現在の状態を取得
*/
fun getData(): SaveData {
return SaveData(level, gold, point)
}
}
###Caretaker Mementoオブジェクトの保管庫
package memento
class MemoryCard {
private val memory = ArrayList<SaveData>()
/**
* セーブ(保存)
*/
fun save(data: SaveData) {
memory.add(data)
}
/**
* ロード(復元)
*/
fun load(index: Int): Game {
val data = memory[index]
return Game(data.level, data.gold, data.point)
}
}
###使う人
package memento
class Client {
init {
// メモリーカードを指す
val memoryCard = MemoryCard()
// ゲームスタート
var game = Game(1, 0, 0)
// 敵撃破
game.enemyDown(1)
game.enemyDown(5)
game.enemyDown(6)
// セーブ
memoryCard.save(game.getData())
// 現在の状態
game.show()
// 敵撃破
game.enemyDown(4)
game.enemyDown(2)
game.enemyDown(8)
// セーブ
memoryCard.save(game.getData())
// 現在の状態
game.show()
// 獲得し損ねたアイテムがあったため最初にセーブした状態へと戻す
game = memoryCard.load(0)
// 現在の状態
game.show()
}
}
###出力結果
[out-put]
レベル:2 所持金:12 経験値:2
レベル:3 所持金:26 経験値:6
レベル:2 所持金:12 経験値:2
以上