观察者模式

观察者模式是软体设计模式的一种。在此种模式中，一个目标物件管理所有相依于它的观察者物件，并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用在即时事件处理系统。
结构.
在上面的UML类图中，codice_1类不直接更新依赖对象的状态，codice_1转而提及codice_3接口（codice_4）来更新状态，这使得codice_1独立于依赖对象的状态是如何更新的。codice_6和codice_7通过将自己的同步于主题的状态实现了codice_3接口。
UML序列图展示了运行时交互：codice_6和codice_7对象调用codice_11于codice_12之上来注册自身。假定codice_12的状态变更了，codice_12调用codice_15于自身之上。codice_15调用codice_4在已注册的codice_6和codice_7对象之上，它从codice_12要来变更了的数据（codice_21）用于更新（同步）自身的状态。
参与者.
参与本模式的各类别列出如下。成员函式以模拟的方式列出。
抽象目标类别，提供一个界面让观察者进行添附与解附作业。此类别内有个不公开的观察者串炼，并透过下列函式(方法)进行作业：
添附函式包涵了一个观察者物件参数。也许是观察者类别的虚拟函式(即更新函式)，或是在非物件导向的设定中所使用的函式指标(更广泛来讲，函式子或是函式物件)。
目标类别，提供了观察者欲追踪的状态。也利用其源类别(例如前述的抽象目标类别)所提供的方法,来通知所有的观察者其状态已经更新。此类别拥有以下函式：
抽象观察者介面，是一个必须被实做的抽象类别。这个类别定义了所有观察者都拥有的更新用介面，此介面是用来接收目标类别所发出的更新通知。此类别含有以下函式：
抽象观察者介面，含有指向目标类别的参考(reference)，以接收来自目标类别的更新状态。此类别含有以下函式：
每个观察者类别都要实做它自己的更新函式，以应对状态更新的情形。
当目标物件改变时，会通过呼叫它自己的通知函式来将通知送给每一个观察者物件，这个通知函式则会去呼叫已经添附在串炼内的观察者更新函式。通知与更新函式可能会有一些参数，好指明是目前目标物件内的何种改变。这么作将可增进观察者的效率(只更新那些改变部份的状态)。
用途.
观察者模式通常与MVC范式有关系。在MVC中，观察者模式被用来降低model与view的耦合程度。一般而言，model的改变会触发通知其他身为观察者的model。而这些model实际上是view。Java Swing就是个范例，示意了model 预期会透过PropertyChangeNotification架构以送出改变的通知给其他view。Model类别是Java bean类别的一员，并拥有与上述目标类别同样的行为。View类别则系结了一些GUI中的可视元素，并拥有与上述观察者类别同样的行为。当应用程式在执行时。使用者将因view做出相应的更新而看见model所产生的变更。
示例.
C++.
下面是C++11实现：
class Subject; //Forward declaration for usage in Observer
class Observer {
public:
 explicit Observer(Subject&amp; subj);
 virtual ~Observer();
 Observer(const Observer&amp;) = delete; // rule of three
 Observer&amp; operator=(const Observer&amp;) = delete;
 virtual void update( Subject&amp; s) const = 0;
private:
 // Reference to a Subject object to detach in the destructor
 Subject&amp; subject;
// Subject is the base class for event generation
class Subject {
public:
 using RefObserver = std::reference_wrapper&lt;const Observer&gt;;
 // Notify all the attached observers
 void notify() {
 for (const auto&amp; x: observers) {
 x.get().update(*this);
 // Add an observer
 void attach(const Observer&amp; observer) {
 observers.push_front(observer);
 
 // Remove an observer
 void detach(Observer&amp; observer) {
 observers.remove_if(
 [&amp;observer](const RefObserver&amp; obj) { 
 return &amp;obj.get()==&amp;observer; 
private:
 std::list&lt;RefObserver&gt; observers;
Observer::Observer(Subject&amp; subj) : subject(subj) {
 subject.attach(*this);
Observer::~Observer() {
 subject.detach(*this);
// Example of usage
class ConcreteObserver: public Observer {
public:
 // Get notification
 void update(Subject&amp;) const override {
 std::cout « "Got a notification" « std::endl;
};
int main() 
 Subject cs;
 ConcreteObserver co1(cs);
 ConcreteObserver co2(cs);
 cs.notify();
程序的输出：
Got a notification
Got a notification
Java.
下面的Java例子接受键盘输入并将每个输入行作为一个事件来处理。当在一个字符串由codice_22提供出来之时，方法codice_23接着被调用，用来通知所有观察者这个事件发生了，这采用了调用它们的更新方法的形式。
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
interface Observer {
 void update(String event);
 
class EventSource {
 List&lt;Observer&gt; observers = new ArrayList&lt;&gt;();
 public void notifyObservers(String event) {
 observers.forEach(observer -&gt; observer.update(event));
 
 public void addObserver(Observer observer) {
 observers.add(observer);
 
 public void scanSystemIn() {
 Scanner scanner = new Scanner(System.in);
 while (scanner.hasNextLine()) {
 String line = scanner.nextLine();
 notifyObservers(line);
public class ObserverDemo {
 public static void main(String[] args) {
 System.out.println("Enter Text: ");
 EventSource eventSource = new EventSource();
 eventSource.addObserver(event -&gt; System.out.println("Received response: " + event));
 eventSource.scanSystemIn();
C#.
C#提供了和接口，还有如何实现这个设计模式的文档。
class Payload {
class Subject : IObservable&lt;Payload&gt; {
 private readonly List&lt;IObserver&lt;Payload» _observers = new List&lt;IObserver&lt;Payload»();
 IDisposable IObservable&lt;Payload&gt;.Subscribe(IObserver&lt;Payload&gt; observer) { 
 if (!_observers.Contains(observer)) {
 _observers.Add(observer);
 return new Unsubscriber(observer, _observers);
 internal void SendMessage(string message) {
 foreach (var observer in _observers) {
 observer.OnNext(new Payload { Message = message });
internal class Unsubscriber : IDisposable {
 private readonly IObserver&lt;Payload&gt; _observer;
 private readonly ICollection&lt;IObserver&lt;Payload» _observers;
 internal Unsubscriber(
 IObserver&lt;Payload&gt; observer,
 ICollection&lt;IObserver&lt;Payload» observers) {
 _observer = observer;
 _observers = observers;
 void IDisposable.Dispose() {
 if (_observer != null &amp;&amp; _observers.Contains(_observer)) {
 _observers.Remove(_observer);
internal class Observer : IObserver&lt;Payload&gt; {
 private string _message;
 public void OnCompleted() {
 public void OnError(Exception error) {
 public void OnNext(Payload value) {
 _message = value.Message;
 internal IDisposable Register(IObservable&lt;Payload&gt; subject) {
 return subject.Subscribe(this);
Python.
from abc import ABC, abstractmethod
class Observer(ABC):
 def __init__(self, subject):
 subject.register_observer(self)
 @abstractmethod
 def update(self): pass
class ObserverA(Observer):
 def update(self, subject, *args, **kwargs):
 print("Got", args, kwargs, "From", subject)
class Subject():
 def __init__(self):
 self.__observers = []
 def register_observer(self, observer):
 self.__observers.append(observer)
 def unregister_observer(self, observer):
 self.__observers.remove(observer)
 def notify_observers(self, *args, **kwargs):
 for observer in self.__observers:
 observer.update(self, *args, **kwargs)
其执行：
»&gt; subject = Subject()
»&gt; observer = ObserverA(subject)
»&gt; subject.notify_observers("test", kw="python")
Got ('test',) {'kw': 'python'} From &lt;__main__.Subject object at 0x736310a21940&gt;