2010年12月6日月曜日

第18章 Memento : 状態を保存する



今回はMementoパターン。undo/redo/snapshotといった機能をカプセル化を破壊することなく提供する方法です。

  • Originator役はMemento役のオブジェクトを生成し、
  • Caretaker役はMemento役のオブジェクトを保持します。

オブジェクトの状態を保存する』という機能は、undo以外にも用途がありそうです。

--

簡単のため、所持金のみ増減するゲームにしてあります。

実行結果
4の目が出た!... 
2の目が出た!... 所持金が半分になった!
1の目が出た!... 所持金が100増えた!
所持金が増えたので状態を保存。現在150円
5の目が出た!... 
3の目が出た!... 
5の目が出た!... 
2の目が出た!... 所持金が半分になった!
2の目が出た!... 所持金が半分になった!
所持金がかなり減ったので状態を復元。現在150円
(中略)
6の目が出た!... 
2の目が出た!... 所持金が半分になった!
所持金がかなり減ったので状態を復元。現在1412円
5の目が出た!... 
2の目が出た!... 所持金が半分になった!
2の目が出た!... 所持金が半分になった!
所持金がかなり減ったので状態を復元。現在1412円
1の目が出た!... 所持金が100増えた!
所持金が増えたので状態を保存。現在1512円
6の目が出た!... 
終了。最終金額1512円

ソースコード
game.py
# -*- coding: utf8 -*-

from random import randint
class Gamer:
    def __init__(self, money):
        self.__money = money

    def getMoney(self): return self.__money
    def bet(self):
        dice = randint(1,6)
        print "%dの目が出た!..." % (dice),
        if dice==1:
            self.__money += 100
            print "所持金が100増えた!"
        elif dice==2:
            self.__money /= 2
            print "所持金が半分になった!"
        else:
            print ""

    def createMemento(self):
        return Memento(self.__money)

    def restoreMemento(self, memento):
        self.__money = memento.getMoney()



class Memento:
    # protected constructor
    def __init__(self, money):
        self.__money = money

    def getMoney(self): return self.__money

main.py
#!/usr/bin/env python
# -*- coding: utf8 -*-

from game import Gamer, Memento
from time import sleep
def main():
    gamer = Gamer(100)
    memento = gamer.createMemento()
    for i in xrange(100):
        gamer.bet()
        if gamer.getMoney() > memento.getMoney():
            memento = gamer.createMemento()
            print "所持金が増えたので状態を保存。現在%d円" % (gamer.getMoney())
        elif gamer.getMoney() < memento.getMoney() / 2:
            gamer.restoreMemento(memento)
            print "所持金がかなり減ったので状態を復元。現在%d円" % (gamer.getMoney())
        sleep(0.5)

    print "終了。最終金額%d円" % (gamer.getMoney())

if __name__=='__main__': main()

0 件のコメント:

コメントを投稿