2020年6月13日土曜日

Ruby のオブザーバパターンを試す

概要

Ruby のデザインパターンの一つであるオブザーバパターンをサンプルコードを実装しながら試してみました
ポイントは Observable の include と実際に何か処理をした際に notify を出すところです

環境

  • macOS 10.15.5
  • Ruby 2.7.1p83

subject.rb

まずは subject を作成します
subject はメイン処理側で通知を飛ばす側になります
まず include Observable が必須になります
これを行うことでオブザーバに通知にするために必要なインスタンスメソッドが使えるようになります

流れとしては先に add_observer でオブザーバとなるオブジェクトを登録しその後メイン処理を実行したあとで通知 (changed -> notify_observers)します
changed がコールされないとサブジェクト側の状態が変わったことにならず通知してもオブザーバ側のメソッドがコールされないので必ず changed をコールしましょう

notify_observers の引数は何でも OK です
通知時にオブザーバ側に渡したい値を指定すれば OK です

  • vim subject.rb
# coding: utf-8
require 'observer'

class Subject
  # Observable を include が必須
  # changed や notify_observers, add_observer や delete_observer が使えるようになる
  include Observable

  def initialize(name)
    @name = name
  end

  attr_reader :name

  def add_my_observer(observer)
    add_observer(observer)
  end

  def delete_my_observer(observer)
    delete_observer(observer)
  end

  def main_method
    puts "メイン処理を開始します"
    # subject 側の処理が完了したら登録したオブザーバに通知します
    changed
    notify_observers(self)
  end
end

observer1.rb

次に通知を受け取る側のオブザーバを作成します
ここでは update という名前のメソッドを実装しておく必要があります
サブジェクト側で notify_observers された際にこの update が呼ばれます
引数は notify_observers で渡されたものがそのまま入ります

  • vim observer1.rb
# coding: utf-8
class Observer1
  # notify_observers が呼ばれるとこのメソッドが発火する
  def update(subject)
    puts "#{subject.name} からの通知が届きました"
  end
end

テスト用メインスクリプト

では動作確認します
まずはサブジェクトとオブザーバを作りましょう
そして add_my_observer でオブザーバを登録します
そしてサブジェクト側のメインのメソッドを実行するとオブザーバの update メソッドがコールされているのが確認できると思います

また delete_observer でオブザーバを削除するとメインの処理を実行しても update がコールされなくなるのが確認できると思います

  • vim main.rb
require './observer1'
require './subject'

subject = Subject.new('my_subject')
observer1 = Observer1.new

subject.add_my_observer(observer1)
subject.main_method

subject.delete_my_observer(observer1)
subject.main_method

=>

メイン処理を開始します
my_subject からの通知が届きました
メイン処理を開始します

最後に

Ruby のオブザーバパターンを試してみました
メイン処理に対して Observable を追加するだけなのでかなり簡単に使えます
オブザーバを複数作成すれば登録/削除を繰り返すだけで状況に合わせて好きなオブザーバが使えるのが嬉しい点かなと思います

参考サイト

0 件のコメント:

コメントを投稿