目次へもどる

フェーズハンドラの改良

さて,経緯はいろいろあるのだが 現状のフェーズ遷移のハンドラの改良を行う. 現状では

  • 開始,終了ハンドラは開始するフェーズおよび終了するフェーズのみが呼び出すメソッドの条件として使える
  • 逆に,遷移条件ハンドラは遷移元,遷移先のフェーズの二つを常に条件に指定する必要がある.

これらは次のような場合に不便である.

  • ある特定のフェーズからの遷移である場合のみに開始ハンドラを設定したい
  • ある特定のフェーズへの遷移である場合のみに終了ハンドラを設定したい*1
  • 遷移条件はほとんど遷移元の状態のみで決まり,遷移先によって条件は不変なのに,遷移先ごとにハンドラを設定しないとならない

これらを解決するために,3つのハンドラの追加様式を統合し,次のようにする.

  • ハンドラの追加メソッドの引数の形式は次の2パターン
    1. phase1, phase2, method
      phase1,phase2は開始ハンドラの場合は順に開始するフェーズ,遷移元のフェーズ,終了ハンドラは終了するフェーズ,遷移先のフェーズ,遷移条件ハンドラは遷移元のフェーズ,遷移先のフェーズを表す.
    2. phase1, method
      上の3引数と異なり,phase1のみを条件とし,phase2は考慮しない.
  • 3引数のハンドラを設定すると,2引数で設定したハンドラのより詳細な条件を指定したバージョンとなる.
  • 3引数のハンドラの条件マッチが優先される.

つまり,例えば

add_start_handler(:phase1, method)

を指定すると,元のフェーズにかかわらず:phase1に遷移した時,methodが実行される. ここに,

add_start_handler(:phase1, :phase2, method2)

を追加すると,元のフェーズが:phase2で,:phase1に遷移した時,method2が実行され, それ以外のフェーズから:phase1に遷移したときはmethodが実行される.

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

*1 これはあまりないと思うが

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2013-08-30 (金) 22:04:23 (4063d)