概要
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 件のコメント:
コメントを投稿