Python.use(better)《14》Observer(14)pull モデル vs. push モデル
|記事一覧|《こちらに移動中です》2007年7月19日 (木)
Python.use(better) # Let’s GoForward
Observer(14)pull モデル vs. push モデル《Jython2.5.0》
■ 概要
GoF の事例を鵜呑みにすると、迂遠なアプローチを余儀なくされるばかりか、Python の洗練された特徴を活かせずに損をします。GoF を模写しても始まりません。GoF が模写したその起源を探ることで、パターンの本質に迫れます。Let's Go Forward (^.^)
Observer(14)pull モデル vs. push モデル★★
共通するインターフェースを実現します。
class ColorListView(JList): def __init__(self, data, changed): JList.__init__(self, listData=data, valueChanged=changed) def value(self): return self.selectedValue
追加したメソッド value は、選択された項目の値を獲得します。ここでは、親クラス JList の属性 selectedValue を参照しています。
class ColorPanel(JPanel, Subject): def __init__(self, listData): self.model = ColorModel() self.listView = ColorListView( data=listData, changed=self.notify_, ) self.panelView = ColorPanelView(preferredSize=(100, 100)) self.add(JScrollPane(self.listView), BorderLayout.CENTER) self.add(self.panelView, BorderLayout.EAST)
メソッド __init__ に変更はありません。
class ColorPanel(JPanel, Subject): def notify_(self, e): value = e.source.value() value = self.model.color(value) self.panelView.background = value if self.observer: self.observer.update_(value)
変更したメソッド notify_ は、インターフェース Subject の規定に従って、自分の状態変化を observer に通知 update_ します。このとき、選択された項目の値 value() を、メソッド update_ の引数を介して、observer に通知します。
class ColorPanel(JPanel, Subject): def color(self): value = self.listView.value() if value: return self.model.color(value) return value
メソッド color に変更はありません。
push モデルでは、一方の状態が変化したときに、依存する側に必要な情報が提供されるので、情報をやり取りする回数が減るため、pull モデルより有利に思えます。
しかし、一度に大量の情報を送信すると、依存する側がその情報の一部だけを必要とするときには、むしろ不利になることがあります。
また、一度に少量の情報を送信すると、情報を提供する相手が多数なら、やはり不利になることがあります。このように、一度に送信する情報量や送信する対象の数など、さまざまな条件を考慮して、どちらの方式を採用するかを決定する必要があります。
《Tips》push/pull モデルをいつ決定するのか
どちらのモデル(push/pull)を採用するかを、コンパイル時ではなく、実行時に決定できると便利です。動的な問題解決については、パターンの午後で紹介します。