[[目次へもどる>PuyoPuyo]] * フェーズハンドラの改良 [#t705b02b] #contents さて,経緯はいろいろあるのだが 現状のフェーズ遷移のハンドラの改良を行う. 現状では - 開始,終了ハンドラは開始するフェーズおよび終了するフェーズのみが呼び出すメソッドの条件として使える - 逆に,遷移条件ハンドラは遷移元,遷移先のフェーズの二つを常に条件に指定する必要がある. これらは次のような場合に不便である. - ある特定のフェーズからの遷移である場合のみに開始ハンドラを設定したい - ある特定のフェーズへの遷移である場合のみに終了ハンドラを設定したい((これはあまりないと思うが)) - 遷移条件はほとんど遷移元の状態のみで決まり,遷移先によって条件は不変なのに,遷移先ごとにハンドラを設定しないとならない これらを解決するために,3つのハンドラの追加様式を統合し,次のようにする. - ハンドラの追加メソッドの引数の形式は次の2パターン ++ phase1, phase2, method~ phase1,phase2は開始ハンドラの場合は順に開始するフェーズ,遷移元のフェーズ,終了ハンドラは終了するフェーズ,遷移先のフェーズ,遷移条件ハンドラは遷移元のフェーズ,遷移先のフェーズを表す. ++ phase1, method~ 上の3引数と異なり,phase1のみを条件とし,phase2は考慮しない. - 3引数のハンドラを設定すると,2引数で設定したハンドラのより詳細な条件を指定したバージョンとなる. - 3引数のハンドラの条件マッチが優先される. つまり,例えば #sh(ruby){{ add_start_handler(:phase1, method) }} を指定すると,元のフェーズにかかわらず:phase1に遷移した時,methodが実行される. ここに, #sh(ruby){{ add_start_handler(:phase1, :phase2, method2) }} を追加すると,元のフェーズが:phase2で,:phase1に遷移した時,method2が実行され, それ以外のフェーズから:phase1に遷移したときはmethodが実行される. #sh(ruby){{ class Phase def add_handler(handler, args) case args.size when 2 phase, method = args handler[phase] = method when 3 # don't care of old/new phase phase1, phase2, method = args handler[[phase1,phase2]] = method else raise(ArgumentError, "wrong number of arguments (#{args.size} for 2 or 3)") end end def add_start_handler(*args) # phase, method # don't care of oldphase # phase, oldphase, method add_handler(@start_handler, args) end def add_end_handler(*args) # phase, method # don't care of nextphase # phase, nextphase, method add_handler(@end_handler, args) end def add_condition_handler(*args) # oldphase, method # don't care of nextphase # oldphase, nextphase, method add_handler(@trans_condition_handler, args) end def get_handler(handler, phase1, phase2) method = handler[[phase1, phase2]] method = handler[phase1] unless method return method end def trans_condition_check cond = get_handler(@trans_condition_handler, @phase, @next_phase) return if cond && !cond.call old = @phase @phase = @next_phase @next_phase = nil # start handler method = get_handler(@start_handler, @phase, old) method.call if method end def change(phase) # end handler method = get_handler(@end_handler, @phase, phase) method.call if method # set next_phase @next_phase = phase # trans condition check trans_condition_check unless wait? end end }}