Ruby/Design Patterns/Observer
Материал из Wiki.crossplatform.ru
Версия от 17:57, 13 сентября 2010; ViGOur (Обсуждение | вклад)
Содержание |
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