Ruby
GoF
observer

GoFのデザインパターン「observer」をrubyで実装してみた

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: **************************************************