Python.use(better)《6》Observer(6)パターン夜明け前
|記事一覧|《こちらに移動中です》2007年6月18日 (月)
Python.use(better) # Let’s GoForward
Observer(6)パターン夜明け前《Jython2.5.0》
■ 概要
GoF の事例を鵜呑みにすると、迂遠なアプローチを余儀なくされるばかりか、Python の洗練された特徴を活かせずに損をします。GoF を模写しても始まりません。GoF が模写したその起源を探ることで、パターンの本質に迫れます。Let's Go Forward (^.^)
Observer(6)パターン夜明け前★★
さらに、別のコンポーネントを導入して、これにも対応できるようにします。
新たなウィンドウを追加します。任意のリスト項目を選択すると、その色情報が文字列としてテキスト領域に表示されます。
class TextView(JTextArea): def __init__(self, subject): JTextArea.__init__(self, lineWrap=True, wrapStyleWord=True) self.subject = subject self.subject.addObserver(self) def redisplay(self): color = self.subject.color() self.text = "" self.append("%s\n"%color)
追加したクラス TextView は、指定された色情報をテキスト(文字列)を使って表示します。ここでは、JTextArea を再利用しています。
メソッド __init__ は、(CanvasView のときと同様に)subject の項目が変更されたときに、その旨を自分にも通知するように登録しておきます。すると、subject の状態に、自分 self が依存することになります。
メソッド redisplay は(CanvasView における paint と違って)項目が変更されたときに、subject から獲得 color() した色情報を、テキストを使って表示ます。
class ColorPanel(JPanel): def valueChanged(self, e): value = e.source.selectedValue self.panelView.background = self.model.color(value) if not self.observer: return if isinstance(self.observer, CanvasView): self.observer.repaint() if isinstance(self.observer, TextView): self.observer.redisplay()
変更したクラス ColorPanel は、新たに追加したコンポーネントにも対処します。
変更したメソッド valueChanged は、自分の最新情報を使って、observer に再描画するように依頼します。このとき、2種類のコンポーネントに対処するためには、observer がどちらに属するインスタンスであるかを判定 isinstance する必要があります。そして、CanvasView なら repaint を使って図形を描き、TextView なら redisplay を使ってテキストを表示します。
ここで問題となるのは、新たな種類のコンポーネントを追加するごとに、メソッド valueChanged 内に、インスタンスの種類を判定 isinstance するコードを追加する必要があることです。なぜなら、異なる対象 observer ごとに、固有のメソッド repaint/redisplay を呼び出す必要があるからです。この問題を回避するには、異なる対象 observer に対して、同じメソッド呼び出しを可能にすることです。それには、共通するインターフェースを抽出して、これを独立したクラスとして規定するのがよいでしょう。