# State パターン # Stateパターン # # Java言語で学ぶデザインパターンと同様の例題をRubyで記述した。 # # coded by Takehiro Kaga # # 3月11日版 # require 'tk' require 'thread' class DayState private_class_method :new # Singletonパターンを適用 @@singleObject = nil def DayState.getInstance @@singleObject = new unless @@singleObject # 唯一のインスタンスを得る @@singleObject end def doClock(context, hour) if hour < 9 or 17 <= hour puts "NightStateへ切替 " + hour.to_s context.changeState(NightState.getInstance) end end def doUse(context) context.recordLog("金庫使用(昼間)") end def doAlarm(context) context.callSecurityCenter("非常ベル(昼間)") end def doPhone(context) context.callSecurityCenter("通常の通話(昼間)") end def toString "[昼間]" end end class NightState private_class_method :new # Singletonパターンを適用 @@singleObject = nil def NightState.getInstance @@singleObject = new unless @@singleObject # 唯一のインスタンスを得る @@singleObject end def doClock(context, hour) if 9 <= hour or hour > 17 context.changeState(DayState.getInstance) end end def doUse(context) context.recordLog("非常:夜間の金庫使用!") end def doAlarm(context) context.callSecurityCenter("非常ベル(夜間)") end def doPhone(context) context.callSecurityCenter("夜間の通話録音") end def toString "[夜間]" end end class SafeFrame private_class_method :new # Singletonパターンを適用 @@singleObject = nil def SafeFrame.getInstance @@singleObject = new unless @@singleObject # 唯一のインスタンスを得る @@singleObject end def initialize @state = DayState.getInstance # イニシャライズ時点では仮に昼を設定 # $timevalue = TkVariable.new("00:00") f1 = TkFrame.new.pack TkLabel.new(f1, 'text'=>'現在時刻は').pack('side'=>'left') $timedisp = TkLabel.new(f1, 'text'=>'00:00').pack('side'=>'left') #$timedisp.configure('text'=>'11:11') #$timedisp.pack f2 = TkFrame.new.pack $text = TkText.new.pack(f2) f3 = TkFrame.new.pack TkButton.new(f3, 'text'=>'金庫使用', 'command'=>proc{@state.doUse(self)}).pack('side'=>'left') TkButton.new(f3, 'text'=>'非常ベル', 'command'=>proc{@state.doAlarm(self)}).pack('side'=>'left') TkButton.new(f3, 'text'=>'非常通話', 'command'=>proc{@state.doPhone(self)}).pack('side'=>'left') TkButton.new(f3, 'text'=>'終了', 'command'=>proc{puts "終了"}).pack('side'=>'left') $text.delete('0.0', 'end') #line ="テキスト表示の試験" #$text.insert 'end', line end def setClock(hour) if hour < 10 clockstring = "0" + hour.to_s + ":00" else clockstring = hour.to_s + ":00" end $timedisp.configure('text'=>clockstring).pack # 時刻表示更新 puts "doClock " + @state.class.name @state.doClock(self, hour) end def changeState(state) puts @state.class.to_s + "から" + state.class.to_s + "へ状態が変化しました。" @state = state puts @state.class.name end def callSecurityCenter( msg ) message = "Call! " + msg + "\n" $text.insert 'end', message end def recordLog( msg ) message = "record ... " + msg + "\n" $text.insert 'end', message end end # ---- Main ---- # frame = SafeFrame.getInstance Thread.start do frame = SafeFrame.getInstance for hour in 0...24 puts hour.to_s frame.setClock(hour) sleep 2 puts "ループを終了しました。" end end Tk.mainloop