- 2022.03.28 Monday
- スポンサーサイト
-
一定期間更新がないため広告を表示しています
- | スポンサードリンク | - | | - | - | pookmark |
- 2017.02.12 Sunday
- Observer パターン きくだけのひと リスナー管理
-
Observer パターン
Observer パターン
ページの問題点
Observer パターン(オブザーバ・パターン)とは、プログラム内のオブジェクトの状態を観察(英: observe)するようなプログラムで使われるデザインパターンの一種。出版-購読型モデルとも呼ばれる。暗黙的呼び出しの原則と関係が深い。
分散イベント処理システムの実装に主に使われる。言語によっては、このパターン扱われる問題は言語が持つイベント処理構文で処理される。リアルタイムのアプリケーション配置の手段として興味深い機能である。
クラス図
このパターンの基本は、(オブザーバまたはリスナーと呼ばれる)1つ以上のオブジェクトを、(サブジェクトと呼ばれる)対象オブジェクトが発生するイベントを観察するために登録する。イベントを発生するオブジェクトは一般に複数のオブザーバを管理する。
以下に、その構造をUMLで描いたもの各クラスの解説
このパターンに登場する各クラスを以下で解説する。各クラスのメンバ関数が列挙されている。
Subject
オブザーバの登録・削除のインタフェースを提供するクラス。Subject クラスはオブザーバのリストを保持する。以下の関数を持つ:
* Attach - Subject を観察するオブザーバのリストに新たなオブザーバを追加する。
* Detach - オブザーバのリストからオブザーバを削除する。
* Notify - リストに登録されている各オブザーバの update() 関数を呼び出すことで変化を通知する。ConcreteSubject
オブザーバが観察したいと考えている状態を提供する。上位クラス(すなわち Subject クラス)の Notify 関数を呼び出すことで、全オブザーバに状態変化を通知する。以下の関数を持つ:
* GetState - サブジェクトの状態を返す。Observer
Subject からの更新通知を受け取る更新(英: update)インタフェースを定義するクラス。Observer クラスは実際のオブザーバの抽象クラスとして使われる。以下の関数を持つ:
* Update - 抽象関数。実際のオブザーバクラスでオーバーライドされる。ConcreteObserver
実際のオブザーバクラス。ConcreteSubject の状態変化の通知を受ける。以下の関数を持つ:
* Update - サブジェクトがこの関数を呼び出すと、Concrete Observer が サブジェクトの Getstate 関数を呼び出してサブジェクトの状態情報を更新する。
イベントが発生すると、各オブザーバはコールバックを受け付ける。これは、オブザーバクラスの仮想関数(上の説明では、update())の場合もあるし、リスナー登録の際に渡される関数ポインタ(より一般的には関数オブジェクト)の場合もある。この通知関数にはいくつかの引数が渡され(発生したイベントを示す引数)、オブザーバがそれを利用する。
それぞれの実体のオブザーバは通知関数を実装し、その定義として実際にイベントを通知されたときの動作を記述する。典型的用法
編集
* ユーザーが何らかの操作をするなどの外部イベントを待つ。イベント駆動型プログラミング参照。
* あるオブジェクトの属性値の変化を待つ。なお、複数の属性値の変化でコールバック関数を呼び出すようにしているとイベントの連鎖的発生を引き起こす。
* メーリングリストで、何らかのイベント(新製品情報など)があったとき、購読者リストに登録している人にメッセージを送る。
Observer パターンは Model View Controller (MVC) パラダイムの実装に使われることも多い。MVC では、モデルとビューの間のループに Observer パターンが使われる。通常、モデルの変化を引き金として、ビュー(オブザーバ)にそれを通知する。コード
Python
Observer パターンを記述したものである。
class Listener:
def __init__(self,
name,
subject
):
self.name = name
subject.register(self)
def update(self,
event
):
print
self. name,
"received event", eventclass Subject:
def __init__(self):
self.listeners = [] きくひとリスト
def register(self,
listener
): きくひと追加
self.listeners.append(listener)
def unregister(self, listener):
self.listeners.remove(listener)
きくひと削除
def notify_listeners(self, event):
for listener in self.listeners:
listener.update(event)
リスナーにnotifiy 通知をアップデートsubject = Subject()
listenerA = Listener("<listener A>", subject)
listenerB = Listener("<listener B>", subject)
# subject には2つのリスナーが登録されている。
subject.notify_listeners ("<event 1>")出力:
< listener A> received event <event 1>
<listener B> received event <event 1>Java
ロックを避けるため、CopyOnWriteArraySetを使用する。
public interface Listener {
public void onEvent();
}import java.util.concurrent.CopyOnWriteArraySet;
public class Subject {
private Set<Listener> listenerSet = new CopyOnWriteArraySet<Listener>();
public void addListener(Listener listener) {
listenerSet.add(listener);
}
private void notifyListeners() {
for (Listener listener : listenerSet) {
listener.onEvent();
}
}
}実装
Observer パターンは各種ライブラリやシステムに実装されている。特にGUIツールキットには必ず含まれる。
* Java Swing ライブラリは Observer パターンを多用している。
* Boost.Signals - C++ STL の拡張。signal/slot モデルを提供する。
* Qt - C++ フレームワークの signal/slot モデル。
* libsigc++ - C++ シグナルプログラミング・テンプレートライブラリ
* sigslot - C++ Signal/Slot ライブラリ
* XLObject - テンプレートベースの C++ signal/slot モデル
* GLib - C言語でのオブジェクトと signals/callbacks の実装(他のプログラミング言語用の実装もある)
* Exploring the Observer Design Pattern - C# と Visual Basic .NET による実装。delegates を利用。
* Using the Observer Pattern - REALbasic による実装
* flash.events - ActionScript 3.0 でのパッケージ(ActionScript 2.0 の mx.events パッケージの後継)
* YUI Event utility - カスタムイベントを Observer パターンで実装
* Py-notify - Python 実装関連項目
* デザインパターン外部リンク
* A sample implementation in .NET
* Observer Pattern in Java
* Observer Pattern implementation in JDK 1.4
* Using the Observer Pattern in .NET
* Definition & UML diagram
* A discussion of fine-grained observers
関連ページ Smalltalk Common Lisp Object System 関数オブジェクトコンテンツは、特に記載されていない限り、CC BY-SA 3.0のもとで利用可能です。
* プライバシーデスクトップ - | whaison | programing design pattern | 12:04 | comments(0) | - | pookmark |