概要
Balking
詳細
Balking=立ち止まる、躊躇する、引き返すの位。野球のボークもこの単語。
実行されると困る条件の場合、実行せず処理の手前で実行を中止する。
実行可能な条件の際に実行するGuarded Suspentionパターンと反対の発想。
Guarded Suspention同様ガード条件を利用して処理を実装する。
このパターンが有用なケースは以下
・特定の条件で処理が不要になるようなケースにムダな処理を省く
要件によりbalkに対する処理を変える
・処理が不要なら何もしない
・balkの発生を知らせる必要がある場合
・何かしら戻り値で知らせる
・例外で知らせる
サンプル仕様
あるRPGの世界を想定。
・敵は1回の戦闘で必ず5体のグループで現れます
・魔王が0.05秒に1回、エンカウントするモンスターを創り出します
・勇者は0.1秒に1回、戦闘を行います。ただしメタルスライムを含まない敵グループとは戦いません
※メタルスラムを含まない=Balkingのガード条件にあたる
クラス構成
Monster : モンスターを表すデータクラス
GameSystem : ゲームシステム。モンスターの生成とメタルスライム限定戦闘コマンドを管理します。
GuardedObjectにあたります。
Devil : 魔王。0.05秒に1回モンスターを創りだす流れ作業者
Hero : 勇者。0.1秒に1回魔王が生成したモンスターにメタルスライムが含まれるかチェックし、
含まれている時だけ戦闘する鬼畜作業者。
サンプルソース
# encoding: utf-8 require "pp" require "thread" class Monster attr_accessor :name def initialize(name) @name = name end end def get_random_1_to_100 rand(100) + 1 end class GameSystem attr_accessor :monsters MONSTER_MASTER = [ Monster.new("スライム"), Monster.new("スライムベス") , Monster.new("バブルスライム"), Monster.new("キングスライム"), Monster.new("メタルスライム") ] def initialize @m = Mutex.new @monsters = [] create_monster end def create_monster @m.synchronize { @monsters = [] 5.times { rand = get_random_1_to_100 case rand when 1..40 @monsters << MONSTER_MASTER[0] when 41..70 @monsters << MONSTER_MASTER[1] when 71..89 @monsters << MONSTER_MASTER[2] when 90..99 @monsters << MONSTER_MASTER[3] else @monsters << MONSTER_MASTER[4] end } puts "create! @monsters" @monsters } end def fight_only_metal_slime @m.synchronize { puts "call fight" return unless has_metal_slime? msg = [] @monsters.each do |monster| msg << "#{monster.name}を倒した" end puts msg.join("\n") } end def has_metal_slime? @monsters.include?(MONSTER_MASTER[4]) end end # 魔王 class Devil < Thread def initialize(game_system) block = lambda { 20.times { game_system.create_monster sleep 0.05 } } super(&block) end end # 勇者 class Hero < Thread def initialize(game_system) block = lambda { 10.times { game_system.fight_only_metal_slime sleep 0.1 } } super(&block) end end game_system = GameSystem.new threads = [] threads << Devil.new(game_system) threads << Hero.new(game_system) threads.each {|t|t.join}
結果
ruby balking.rb create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters $ruby balking.rb create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight create! @monsters create! @monsters call fight スライムを倒した スライムを倒した スライムベスを倒した メタルスライムを倒した スライムベスを倒した create! @monsters
関連
Guarded Suspention
http://d.hatena.ne.jp/tbpg/20130915/1379254661