observerパターンは、観察対象の状態が変化すると観察舎に対して通知を送るような仕組みです。
rubyには observer
が標準で組み込まれているので、今回はそれを用いて以下のように実装しました。
require 'observer'
# Observer役
class Observer
end
# Observer役
class DigitObserver < Observer
def update(number)
puts "DigitObserver: #{number}"
end
end
# Observer役
# Observer役の追加が非常に簡単である。
class GraphObserver < Observer
def update(number)
string = '*'
puts "GraphObserver: #{string*number}"
end
end
# Subject役
class NumberGenerator
include Observable
end
# ConcreteSubject役
class RandomNumberGenerator < NumberGenerator
def run
random = Random.new
for i in 1..20 do
number = random.rand(50)
changed
notify_observers(number)
end
end
end
# ConcreteSubject役
# Observer役と同じく、観察対象の追加が非常に簡単に実装できる。
class IncrementNumberGenerator < NumberGenerator
def initialize(start_int, end_int, interval)
unless (end_int - start_int) % interval == 0
raise '正しい初期値を。'
end
@start_int = start_int
@end_int = end_int
@interval = interval
end
def run
for i in 0..(@end_int - @start_int) / @interval
changed
notify_observers(@start_int + i * @interval)
end
end
end
generator = RandomNumberGenerator.new
generator.add_observer(DigitObserver.new)
generator.add_observer(GraphObserver.new)
generator.run
generator = IncrementNumberGenerator.new(10, 50, 5)
generator.add_observer(DigitObserver.new)
generator.add_observer(GraphObserver.new)
generator.run
結果
DigitObserver: 15
GraphObserver: ***************
DigitObserver: 23
GraphObserver: ***********************
DigitObserver: 0
GraphObserver:
DigitObserver: 5
GraphObserver: *****
DigitObserver: 41
GraphObserver: *****************************************
DigitObserver: 6
GraphObserver: ******
DigitObserver: 30
GraphObserver: ******************************
DigitObserver: 41
GraphObserver: *****************************************
DigitObserver: 6
GraphObserver: ******
DigitObserver: 28
GraphObserver: ****************************
DigitObserver: 15
GraphObserver: ***************
DigitObserver: 31
GraphObserver: *******************************
DigitObserver: 47
GraphObserver: ***********************************************
DigitObserver: 11
GraphObserver: ***********
DigitObserver: 30
GraphObserver: ******************************
DigitObserver: 29
GraphObserver: *****************************
DigitObserver: 41
GraphObserver: *****************************************
DigitObserver: 34
GraphObserver: **********************************
DigitObserver: 24
GraphObserver: ************************
DigitObserver: 13
GraphObserver: *************
DigitObserver: 10
GraphObserver: **********
DigitObserver: 15
GraphObserver: ***************
DigitObserver: 20
GraphObserver: ********************
DigitObserver: 25
GraphObserver: *************************
DigitObserver: 30
GraphObserver: ******************************
DigitObserver: 35
GraphObserver: ***********************************
DigitObserver: 40
GraphObserver: ****************************************
DigitObserver: 45
GraphObserver: *********************************************
DigitObserver: 50
GraphObserver: **************************************************