觀察者模式

觀察者模式是軟體設計模式的一種。在此種模式中，一個目標物件管理所有相依於它的觀察者物件，並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用在即時事件處理系統。參與類別.參與本模式的各類別列出如下。成員函式以模擬的方式列出。抽象目標類別.此抽象類別提供一個介面讓觀察者進行添附與解附作業。此類別內有個不公開的觀察者串鍊，並透過下列函式(方法)進行作業添附函式包涵了一個觀察者物件引數。也許是觀察者類別的虛擬函式(即更新函式)，或是在非物件導向的設定中所使用的函式指標(更廣泛來講，函式子或是函式物件)。目標類別.此類別提供了觀察者欲追蹤的狀態。也利用其源類別(例如前述的抽象目標類別)所提供的方法,來通知所有的觀察者其狀態已經更新。此類別擁有以下函式抽象觀察者介面.抽象觀察者類別是一個必須被實做的抽象類別。這個類別定義了所有觀察者都擁有的更新用介面，此介面是用來接收目標類別所發出的更新通知。此類別含有以下函式觀察者類別.這個類別含有指向目標類別的參考(reference)，以接收來自目標類別的更新狀態。此類別含有以下函式每個觀察者類別都要實做它自己的更新函式，以應對狀態更新的情形。當目標物件改變時，會透過呼叫它自己的通知函式來將通知送給每一個觀察者物件，這個通知函式則會去呼叫已經添附在串鍊內的觀察者更新函式。通知與更新函式可能會有一些引數，好指明是目前目標物件內的何種改變。這麼作將可增進觀察者的效率(只更新那些改變部份的狀態)。用途.觀察者模式通常與 MVC 正規化有關係。在 MVC 中，觀察者模式被用來降低 model 與 view 的耦合程度。一般而言， model 的改變會觸發通知其他身為觀察者的 model 。而這些 model 實際上是 view 。 Java Swing 就是個範例，示意了 model 預期會透過 PropertyChangeNotification 架構以送出改變的通知給其他 view 。 Model 類別是 Java bean 類別的一員，並擁有與上述目標類別同樣的行為。 View 類別則繫結了一些 GUI 中的可視元素，並擁有與上述觀察者類別同樣的行為。當應用程式在執行時。使用者將因 view 做出相應的更新而看見 model 所產生的變更。示例.Python.class AbstractSubject(object):def register(self, listener):raise NotImplementedError("Must subclass me")def deregister(self, listener):raise NotImplementedError("Must subclass me")def notify_listeners(self, event):raise NotImplementedError("Must subclass me")class Listener(object):def __init__(self, name, subject):self.name = namesubject.register(self)def notify(self, event):print(self.name, "received event", event)class Subject(AbstractSubject):def __init__(self):self.listeners = []self.data = Nonedef getUserAction(self):self.data = raw_input('Enter something to do:')return self.data# Implement abstract Class AbstractSubjectdef register(self, listener):self.listeners.append(listener)def deregister(self, listener):self.listeners.remove(listener)def notify_listeners(self, event):for listener in self.listeners:listener.notify(event)if __name__=="__main__":# make a subject object to spy onsubject = Subject()# register two listeners to monitor it.listenerA = Listener("", subject)listenerB = Listener("", subject)# simulated eventsubject.notify_listeners ("")# outputs:##action = subject.getUserAction()subject.notify_listeners(action)#Enter something to do:hello# outputs:#  received event hello#  received event helloC#.C#和其他使用.NET Framework的語言一般無需使用介面和類實現典型的觀察者模式，但是這裡依然給一個例子。using System;using System.Collections;namespace Wikipedia.Patterns.Strategy// IObserver --&gt; interface for the observerpublic interface IObserver// called by the subject to update the observer of any change// The method parameters can be modified to fit certain criteriavoid Update(string message);public class Subject// use array list implementation for collection of observersprivate ArrayList observers;// constructorpublic Subject()observers = new ArrayList();public void Register(IObserver observer)// if list does not contain observer, addif (!observers.Contains(observer))observers.Add(observer);public void Deregister(IObserver observer)// if observer is in the list, removeif (observers.Contains(observer))observers.Remove(observer);public void Notify(string message)// call update method for every observerforeach (IObserver observer in observers)observer.Update(message);// Observer1 --&gt; Implements the IObserverpublic class Observer1 : IObserverpublic void Update(string message)Console.WriteLine("Observer1:" + message);// Observer2 --&gt; Implements the IObserverpublic class Observer2 : IObserverpublic void Update(string message)Console.WriteLine("Observer2:" + message);// Test classpublic class ObserverTester[STAThread]public static void Main()Subject mySubject = new Subject();IObserver myObserver1 = new Observer1();IObserver myObserver2 = new Observer2();// register observersmySubject.Register(myObserver1);mySubject.Register(myObserver2);mySubject.Notify("message 1");mySubject.Notify("message 2");C++.using namespace std;// The Abstract Observerclass ObserverBoardInterfacepublic:virtual void update(float a,float b,float c) = 0;// Abstract Interface for Displaysclass DisplayBoardInterfacepublic:virtual void show() = 0;// The Abstract Subjectclass WeatherDataInterfacepublic:virtual void registerob(ObserverBoardInterface* ob) = 0;virtual void removeob(ObserverBoardInterface* ob) = 0;virtual void notifyOb() = 0;// The Concrete Subjectclass ParaWeatherData: public WeatherDataInterfacepublic:void SensorDataChange(float a,float b,float c)m_humidity = a;m_temperature = b;m_pressure = c;notifyOb();void registerob(ObserverBoardInterface* ob)m_obs.push_back(ob);void removeob(ObserverBoardInterface* ob)m_obs.remove(ob);protected:void notifyOb()list::iterator pos = m_obs.begin();while (pos != m_obs.end())((ObserverBoardInterface* )(*pos))-&gt;update(m_humidity,m_temperature,m_pressure);(dynamic_castshow();++pos;private:float m_humidity;float m_temperature;float m_pressure;list m_obs;// A Concrete Observerclass CurrentConditionBoard : public ObserverBoardInterface, public DisplayBoardInterfacepublic:CurrentConditionBoard(WeatherDataInterface&amp; a):m_data(a)m_data.registerob(this);void show()cout«"_____CurrentConditionBoard_____"«endl;cout«"humidity: "«m_h«endl;cout«"temperature: "«m_t«endl;cout«"pressure: "«m_p«endl;cout«"_______________________________"«endl;void update(float h, float t, float p)m_h = h;m_t = t;m_p = p;private:float m_h;float m_t;float m_p;WeatherDataInterface&amp; m_data;// A Concrete Observerclass StatisticBoard : public ObserverBoardInterface, public DisplayBoardInterfacepublic:StatisticBoard(WeatherDataInterface&amp; a):m_maxt(-1000),m_mint(1000),m_avet(0),m_count(0),m_data(a)m_data.registerob(this);void show()cout«"________StatisticBoard_________"«endl;cout«"lowest temperature: "«m_mint«endl;cout«"highest temperature: "«m_maxt«endl;cout«"average temperature: "«m_avet«endl;cout«"_______________________________"«endl;void update(float h, float t, float p)++m_count;if (t&gt;m_maxt)m_maxt = t;if (t Comes from tiago: I'm a student of English亦可參考https://web.archive.org/web/20100330025802/http://www.javaworld.com/javaworld/javaqa/2001-05/04-qa-0525-observer.html