Code Blocks as Observers
A common Ruby variation on the Observer pattern is our old friend the code block. The code becomes a lot simpler if we can just pass in a code block as our listener. Because the Ruby library Observable does not support code blocks, perhaps we can find a use for a slightly modified version of our Subject module after all:
module Subject def initialize @observers=[] end def add_observer(&observer) @observers << observer end def delete_observer(observer) @observers.delete(observer) end def notify_observers @observers.each do |observer| observer.call(self) end end end class Employee include Subject attr_accessor :name, :title, :salary def initialize( name, title, salary ) super() @name = name @title = title @salary = salary end def salary=(new_salary) @salary = new_salary notify_observers end end
The advantage of using code blocks as observers is that they simplify the code; we no longer need a separate class for the observers. To add an observer, we just call add_observer and pass in a code block:
fred = Employee.new('Fred', 'Crane Operator', 30000) fred.add_observer do |changed_employee| puts("Cut a new check for #{changed_employee.name}!") puts("His salary is now #{changed_employee.salary}!") end
This example passes a two-line code block as an observer into Employee object. By the time those two lines reach the Employee object, they are all wrapped up in a convenient Proc object and are set to act as a ready-made observer. When Fred's salary changes, the Employee object calls the call method on the Proc, and the two puts get fired.