RussOlsenObserverMethod

従業員(employee)クラスとそのnew.

observer88-0.rb
class Employee
  attr_reader :name
  attr_accessor :title, :salary

  def initialize(name, title, salary)
    @name, @title, @salary = name, title, salary
  end
end

p fred = Employee.new("Fred Flintstone", "Crane Operator", 30000.0)

p fred.salary = 35000.0
p fred

経理部門への素直な通知法.

class Employee
  attr_reader :name
#  attr_accessor :title, :salary
  attr_reader :title, :salary

  def initialize(name, title, salary, payroll)
    @name, @title, @salary = name, title, salary
    @payroll = payroll
  end
  
  def salary=(new_salary)
    @salary = new_salary
    @payroll.update(self)
  end
end

class Payroll
  def update(changed_employee)
    puts("#{changed_employee.name}のために小切手を切ります!")
    puts("彼の給料はいま#{changed_employee.salary}です!")
  end
end

payroll = Payroll.new
p fred = Employee.new("Fred Flintstone", "Crane Operator", 30000.0, payroll)

p fred.salary = 35000.0
p fred

通知を受けるより良い方法に.observers=[]を利用.

class Employee
  attr_reader :name
  attr_reader :title, :salary

  def initialize(name, title, salary)
    @name, @title, @salary = name, title, salary
    @observers = []
  end
  
  def salary=(new_salary)
    @salary = new_salary
#    @payroll.update(self)
    notify_observers
  end

  def notify_observers
    @observers.each do |observer|
      observer.update(self)
    end
  end

  def add_observer(observer)
    @observers << observer
  end

  def del_observer(observer)
    @observers.delete observer
  end
end

class Payroll
  def update(changed_employee)
    puts("#{changed_employee.name}のために小切手を切ります!")
    puts("彼の給料はいま#{changed_employee.salary}です!")
  end
end

class TaxMan
  def update(changed_employee)
    puts("#{changed_employee.name}に新しい税金の請求書を送ります!")
  end
end

fred = Employee.new("Fred Flintstone", "Crane Operator", 30000.0)

payroll = Payroll.new
fred.add_observer(payroll)
tax_man = TaxMan.new
fred.add_observer(tax_man)
fred.salary = 35000.0

オブザーバーに対する責務をクラスとして分離.

class Subject
#  def initialize(name, title, salary)
  def initialize
    @observers = []
  end
  
  def notify_observers
    @observers.each do |observer|
      observer.update(self)
    end
  end

  def add_observer(observer)
    @observers << observer
  end

  def del_observer(observer)
    @observers.delete observer
  end
end
class Employee < Subject
  attr_reader :name
  attr_reader :title, :salary

  def initialize(name, title, salary)
    super()
    @name, @title, @salary = name, title, salary
#    @observers = []
  end
  
  def salary=(new_salary)
    @salary = new_salary
#    @payroll.update(self)
    notify_observers
  end
end

class Payroll
  def update(changed_employee)
    puts("#{changed_employee.name}のために小切手を切ります!")
    puts("彼の給料はいま#{changed_employee.salary}です!")
  end
end

class TaxMan
  def update(changed_employee)
    puts("#{changed_employee.name}に新しい税金の請求書を送ります!")
  end
end

fred = Employee.new("Fred Flintstone", "Crane Operator", 30000.0)

payroll = Payroll.new
fred.add_observer(payroll)
tax_man = TaxMan.new
fred.add_observer(tax_man)
fred.salary = 35000.0

それのmodule化.

#class Subject
module Subject
  def initialize
    @observers = []
  end
  
  def notify_observers
    @observers.each do |observer|
      observer.update(self)
    end
  end

  def add_observer(observer)
    @observers << observer
  end

  def del_observer(observer)
    @observers.delete observer
  end
end

#class Employee < Subject
class Employee
  include Subject
  attr_reader :name
  attr_reader :title, :salary

  def initialize(name, title, salary)
    super()
    @name, @title, @salary = name, title, salary
#    @observers = []
  end
  
  def salary=(new_salary)
    @salary = new_salary
#    @payroll.update(self)
    notify_observers
  end
end

class Payroll
  def update(changed_employee)
    puts("#{changed_employee.name}のために小切手を切ります!")
    puts("彼の給料はいま#{changed_employee.salary}です!")
  end
end

class TaxMan
  def update(changed_employee)
    puts("#{changed_employee.name}に新しい税金の請求書を送ります!")
  end
end

fred = Employee.new("Fred Flintstone", "Crane Operator", 30000.0)

payroll = Payroll.new
fred.add_observer(payroll)
tax_man = TaxMan.new
fred.add_observer(tax_man)
fred.salary = 35000.0

さらにrubyに標準装備のObservableクラスの利用.

require 'observer'

class Employee
  include Observable
  attr_reader :name
  attr_reader :title, :salary

  def initialize(name, title, salary)
    super()
    @name, @title, @salary = name, title, salary
#    @observers = []
  end
  
  def salary=(new_salary)
    @salary = new_salary
    changed
    notify_observers(self)
  end

  def add_observer(observer)
    @observers << observer
  end

  def del_observer(observer)
    @observers.delete observer
  end
end

class Payroll
  def update(changed_employee)
    puts("#{changed_employee.name}のために小切手を切ります!")
    puts("彼の給料はいま#{changed_employee.salary}です!")
  end
end

class TaxMan
  def update(changed_employee)
    puts("#{changed_employee.name}に新しい税金の請求書を送ります!")
  end
end

fred = Employee.new("Fred Flintstone", "Crane Operator", 30000.0)

payroll = Payroll.new
fred.add_observer(payroll)
tax_man = TaxMan.new
fred.add_observer(tax_man)
fred.salary = 35000.0

Observer Method使用上の注意

  • データ渡し push型とpull型
  • 頻度
  • タイミング
  • subjectがすべての監視をする必要があるのか.
  • observerが自動的にできないか?
Last modified:2016/07/19 12:42:27
Keyword(s):
References:[MultiScale14]