Ruby/Design Patterns/Observer

Материал из Wiki.crossplatform.ru

Перейти к: навигация, поиск

Содержание

Add another observer

class PaymentObserver
  def update( changed_employee )
    puts("Cut a new check for #{changed_employee.name}!")
    puts("His salary is now #{changed_employee.salary}!")
  end
end
class Employee
  attr_reader :name, :title
  attr_reader :salary
  def initialize( name, title, salary )
    @name = name
    @title = title
    @salary = salary
    @observers = []
  end
    def salary=(new_salary)
      @salary = new_salary
      notify_observers
    end
    def notify_observers
      @observers.each do |observer|
        observer.update(self)
      end
    end
 
    def add_observer(observer)
      @observers << observer
    end
 
    def delete_observer(observer)
      @observers.delete(observer)
    end
 
end
fred = Employee.new("Fred", "Crane Operator", 30000.0)
payroll = PaymentObserver.new
fred.add_observer( payroll )
fred.salary=35000.0
class TaxMan
  def update( changed_employee )
    puts("Send #{changed_employee.name} a new tax bill!")
  end
end
tax_man = TaxMan.new
fred.add_observer(tax_man)
fred.salary=90000.0



Code Blocks as Observers

module Observable
  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 Observable
  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
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



Coupling Systems Loosely with Callbacks

class MyObject 
  def initialize
    setup_listeners
  end
  def produce_widget(color)
    notify(:new_widget, color)
  end
 
  def setup_listeners
    @EventDispatcher_listeners = {}
  end
  def subscribe(event, &callback)
    (@EventDispatcher_listeners[event] ||= []) << callback
  end
  def notify(event, *args)
    if @EventDispatcher_listeners[event]
      @EventDispatcher_listeners[event].each do |m|
        m.call(*args) if m.respond_to? :call
      end
    end
    return nil
  end  
end
class MyObjectObserver
  def initialize(factory)
    @counts = Hash.new(0)
    factory.subscribe(:new_widget) do |color|
      @counts[color] += 1
      puts "#{@counts[color]} #{color} widget(s) created."
    end
  end
end
f1 = MyObject.new
MyObjectObserver.new(f1)
f1.produce_widget("red")
f1.produce_widget("green")
f1.produce_widget("red")



Staying Informed (Observer pattern)

class PaymentObserver
  def update( changed_employee )
    puts("Cut a new check for #{changed_employee.name}!")
    puts("His salary is now #{changed_employee.salary}!")
  end
end
class Employee
  attr_reader :name, :title
  attr_reader :salary
  def initialize( name, title, salary )
    @name = name
    @title = title
    @salary = salary
    @observers = []
  end
    def salary=(new_salary)
      @salary = new_salary
      notify_observers
    end
    def notify_observers
      @observers.each do |observer|
        observer.update(self)
      end
    end
 
    def add_observer(observer)
      @observers << observer
    end
 
    def delete_observer(observer)
      @observers.delete(observer)
    end
 
end
fred = Employee.new("Fred", "Crane Operator", 30000.0)
payroll = PaymentObserver.new
fred.add_observer( payroll )
fred.salary=35000.0