Java: イベント駆動によるModelとViewの分離 – Observer パターン


よくGUIやWebアプリの簡単なサンプルソースなどは、UIとアプリケーションのロジックが同じクラスまたはメソッドに書かれている場合が多い。それはそのサンプルがある特定の機能や関数の紹介の為に簡潔に書いているのだが、仮にいざそのソースを元にアプリを作りこんで機能の追加を行っていくとUIとアプリのロジックは分離したほうが保守・拡張と共に行い易い。

下記のプログラムは1秒毎に数値をカウントし、それを2進数と10進数でGUI上のラベルに出力する機能をモデルとビューに分けている。すなわち、数値のカウントをするモデルと数値をUIに表示するビューに。(いくつかの言語ではGUIの部品としてタイマーがあるようだが。。)

実行結果

count_timer01

クラス図

countmodel_view_class

インスタンスの生成はコンストラクタで行うのがいいのですが、はしょっている。さて、これまでに何らかのフレームワークを使っていた方には上クラス図はMVCの説明図として見慣れているかもしれない。今回ModelとViewを繋ぐControllerの役割はCountListenerが担っている(下記コードではCountChangeEvent経由でModelインスタンスを渡すのみだが)。

処理手順

ビュー側で自身のインスタンスをモデルに登録し(モデル.addCountListener(ビュー))、モデルのデータが更新された場合、モデル→ビューへイベントを送出。イベント内部にモデルのデータがあり、そのデータでビューがUIを更新する。イベントの発生順序等は下図のシーケンス図のようになる。

シーケンス図

countmodel_view_sequence

無限ループに注意

ビューを更新するイベントリスナーのメソッド(ここではcountChanged())で再度モデルのプロパティ変更メソッド(ここではsetCount())を用いると、再度イベント通知処理(notifyToListeners())が発生することで、無限ループになるので注意が必要。

ビューの追加手順

ビューを追加する際の手順は、ビューのインスタンスをモデルのリスナーに登録し(addCountListener())、ビュー自身がリスナーのメソッドを実装することで(countChanged())、モデルからのイベントを受け取ることが出来る。

そういえば最近はIDEの方でバインド設定したり、ObservableList等があるのであまり意識することがなくなってきたなぁ。

ソースコード

関連記事 (Related Articles):


コメントを残す