#参考
@kidachi1さんの記事のRubyの記事のソースコードをpythonに書き換えてます。
https://qiita.com/kidach1/items/ce18d2a926c558159689
@kidachi1さん、いつもありがとうございます。
#概要
Rubyによるデザインパターン第5章。
Observer Pattern。
Rubyによるデザインパターン5原則に則って理解する。
この記事はPython
#どんなパターンか
あるオブジェクトの状態に関心のあるオブジェクトに、都度通知を送る。
ニュースの発信源(Subject)とニュースの消費者(Observer)間に綺麗なインターフェイスを用意する。
###Subject
あるニュースを配信するクラス
###Observer
あるニュースを得ることに関心があるクラス
#メリット
ニュースの発信者と受信者の間の依存関係を排除する。
#問題のあるコード
従業員の給与の変化を経理部門に伝えるシステム
#従業員クラス
class Employee:
def __init__(self, name, title, salary, payroll):
self.name = name
self.title = title
self.salary = salary
self.payroll = payroll
def update_salary(self, new_salary):
self.salary = new_salary
self.payroll.update(self)
#経理部門クラス
class Payroll:
def __init__(self):
pass
def update(self, changed_employee): # Subjectオブジェクトを受け取る
print ( changed_employee.name + "の給料が" + str(changed_employee.salary) + "ドルに上がりました!" )
#クラスの利用
payroll = Payroll()
employee = Employee( "tsuji","leader", 1000, payroll )
employee.update_salary(2000)
#tsujiの給料が2000ドルに上がりました!
#問題
もし経理部門以外にも通知したくなったら?
→今はEmployeeクラスに手を入れる必要がある。
本質的にはEmployeeに対する変更など何もないにも関わらず・・。
そこで、
変化する事項(「従業員の給与の変更」というニュースを誰が受け取るか)を、Employeeオブジェクトから分離する。
→必要なのは、Employeeオブジェクトの変化に関心のあるオブジェクトの一覧。
#従業員クラス
class Employee2:
def __init__(self, name, title, salary ):
self.name = name
self.title = title
self.salary = salary
self.observers = []
def add_observer(self, observer):
self.observers.append(observer)
def update_salary(self, new_salary):
self.salary = new_salary
self.notify_observers()
def notify_observers(self):
for observer in self.observers :
observer.update(self)
#経理部クラス
class Payroll:
def __init__(self):
pass
def update(self, changed_employee): # Subjectオブジェクトを受け取る
print ( changed_employee.name + "の給料が" + str(changed_employee.salary) + "ドルに上がりました!" )
print ( "経理部門は" + changed_employee.name + "に小切手を切ります!")
#税務署員クラス
class Taxman:
def __init__(self):
pass
def update(self, changed_employee): # Subjectオブジェクトを受け取る
print ( changed_employee.name + "の給料が" + str(changed_employee.salary) + "ドルに上がりました!" )
print ( "税務署員は" + changed_employee.name + "に新しい税金請求書を送ります!")
#クラスの利用
taxman = Taxman()
payroll = Payroll()
employee2 = Employee2("daisuke","member", 3000)
employee2.add_observer(payroll)
employee2.add_observer(taxman)
employee2.update_salary(4000)
#まとめ
変わるもの(オブザーバー)と変わらないもの(サブジェクト)を分離して、変化に強い構造へ
#Strategyパターンとの比較
###形は似ている
Observerパターン:サブジェクトがオブザーバーを呼び出す
Strategyパターン:コンテキストがストラテジを呼び出す
###違いは目的
Observerパターン:サブジェクトで発生したイベントをオブザーバーへ通知する
Strategyパターン:コンテキストが、何か特定の処理を行うためにストラテジを呼び出す