Menu
Home Explore People Places Arts History Plants & Animals Science Life & Culture Technology
On this page
Observer pattern
Software design pattern based on an event-updated object with a list of dependents

In software design and software engineering, the observer pattern is a software design pattern in which an object, called the subject (also known as event source or event stream), maintains a list of its dependents, called observers (also known as event sinks), and automatically notifies them of any state changes, typically by calling one of their methods. The subject knows its observers through a standardized interface and manages the subscription list directly.

This pattern creates a one-to-many dependency where multiple observers can listen to a single subject, but the coupling is typically synchronous and direct—the subject calls observer methods when changes occur, though asynchronous implementations using event queues are possible. Unlike the publish-subscribe pattern, there is no intermediary broker; the subject and observers have direct references to each other.

It is commonly used to implement event handling systems in event-driven programming, particularly in-process systems like GUI toolkits or MVC frameworks. This makes the pattern well-suited to processing data that arrives unpredictably—such as user input, HTTP requests, GPIO signals, updates from distributed databases, or changes in a GUI model.

We don't have any images related to Observer pattern yet.
We don't have any YouTube videos related to Observer pattern yet.
We don't have any PDF documents related to Observer pattern yet.
We don't have any Books related to Observer pattern yet.

Overview

The observer design pattern is a behavioural pattern listed among the 23 well-known "Gang of Four" design patterns that address recurring design challenges in order to design flexible and reusable object-oriented software, yielding objects that are easier to implement, change, test, and reuse.1

The observer pattern addresses the following requirements:2

  • A one-to-many dependency between objects should be defined without making the objects tightly coupled.
  • When one object changes state, an open-ended number of dependent objects should be updated automatically.
  • An object can notify multiple other objects.

The naive approach would be for one object (subject) to directly call specific methods on each dependent object. This creates tight coupling because the subject must know the concrete types and specific interfaces of all dependent objects, making the code inflexible and hard to extend. However, this direct approach may be preferable in performance-critical scenarios (such as low-level kernel structures or real-time systems) where the overhead of abstraction is unacceptable and compile-time optimization is crucial.

The observer pattern provides a more flexible alternative by establishing a standard notification protocol:

  1. Define Subject and Observer objects with standardized interfaces.
  2. When a subject changes state, all registered observers are notified and updated automatically.
  3. The subject manages its own state while also maintaining a list of observers and notifying them of state changes by calling their update() operation.
  4. The responsibility of observers is to register and unregister themselves with a subject (in order to be notified of state changes) and to update their state (to synchronize it with the subject's state) when they are notified.

This approach makes subject and observers loosely coupled through interface standardization. The subject only needs to know that observers implement the update() method—it has no knowledge of observers' concrete types or internal implementation details. Observers can be added and removed independently at run time.

Differences with publish-subscribe pattern

While both patterns enable one-to-many communication, the observer pattern and publish-subscribe pattern differ significantly in their architecture and use cases:

FeatureObserver PatternPublish–Subscribe Pattern
CouplingTightly coupled — the subject holds direct references to its observers via a standardized interface.Loosely coupled — publishers and subscribers are unaware of each other.
CommunicationDirect — subject calls observer methods, typically synchronously but can be asynchronous with queues.Indirect — a broker (message bus, event manager, etc.) routes messages.
Knowledge of ParticipantsSubject knows its observers via interfaces.Publisher and subscriber don't know each other.
ScalabilityLess scalable for distributed systems due to tight coupling; suitable for in-process systems like GUI frameworks.More scalable — decoupled participants allow distributed systems and asynchronous communication.
Synchronous or AsynchronousTypically synchronous but can be asynchronous with proper design (e.g., event queues).Typically asynchronous (events queued, pushed via broker), but can be synchronous in some cases.
FilteringLimited — observers receive all notifications but can filter internally in their update() method.Rich filtering — brokers can filter messages by topic, content, or other criteria.
Fault ToleranceObserver failures can affect the subject; mitigated with error handling (e.g., try-catch).Broker provides isolation — publisher/subscriber failures don't directly affect each other.
Typical UsageIn-process systems like GUI toolkits, MVC patterns, object notification.Distributed systems, microservices, event-driven architectures.

Strong vs. weak reference

The observer pattern can cause memory leaks, known as the lapsed listener problem, because in a basic implementation, it requires both explicit registration and explicit deregistration, as in the dispose pattern, because the subject holds strong references to the observers, keeping them alive. This can be prevented if the subject holds weak references to the observers.

Coupling and typical publish-subscribe implementations

Typically, the observer pattern is implemented so that the subject being observed is part of the object for which state changes are being observed (and communicated to the observers). This type of implementation is considered tightly coupled, forcing both the observers and the subject to be aware of each other and have access to their internal parts, creating possible issues of scalability, speed, message recovery and maintenance (also called event or notification loss), the lack of flexibility in conditional dispersion and possible hindrance to desired security measures. In some (non-polling) implementations of the publish-subscribe pattern, this is solved by creating a dedicated message queue server (and sometimes an extra message handler object) as an extra stage between the observer and the object being observed, thus decoupling the components. In these cases, the message queue server is accessed by the observers with the observer pattern, subscribing to certain messages and knowing (or not knowing, in some cases) about only the expected message, while knowing nothing about the message sender itself; the sender may also know nothing about the observers. Other implementations of the publish-subscribe pattern, which achieve a similar effect of notification and communication to interested parties, do not use the observer pattern.34

In early implementations of multi-window operating systems such as OS/2 and Windows, the terms "publish-subscribe pattern" and "event-driven software development" were used as synonyms for the observer pattern.5

The observer pattern, as described in the Design Patterns book, is a very basic concept and does not address removing interest in changes to the observed subject or special logic to be performed by the observed subject before or after notifying the observers. The pattern also does not deal with recording change notifications or guaranteeing that they are received. These concerns are typically handled in message-queueing systems, in which the observer pattern plays only a small part.

Related patterns include publish–subscribe, mediator and singleton.

Uncoupled

The observer pattern may be used in the absence of publish-subscribe, as when model status is frequently updated. Frequent updates may cause the view to become unresponsive (e.g., by invoking many repaint calls); such observers should instead use a timer. Instead of becoming overloaded by change message, the observer will cause the view to represent the approximate state of the model at a regular interval. This mode of observer is particularly useful for progress bars, in which the underlying operation's progress changes frequently.

Structure

UML class and sequence diagram

In this UML class diagram, the Subject class does not update the state of dependent objects directly. Instead, Subject refers to the Observer interface (update()) for updating state, which makes the Subject independent of how the state of dependent objects is updated. The Observer1 and Observer2 classes implement the Observer interface by synchronizing their state with subject's state.

The UML sequence diagram shows the runtime interactions: The Observer1 and Observer2 objects call attach(this) on Subject1 to register themselves. Assuming that the state of Subject1 changes, Subject1 calls notify() on itself. notify() calls update() on the registered Observer1 and Observer2objects, which request the changed data (getState()) from Subject1 to update (synchronize) their state.

UML class diagram

Example

While the library classes java.util.Observer and java.util.Observable exist, they have been deprecated in Java 9 because the model implemented was quite limited.

Below is an example written in Java that takes keyboard input and handles each input line as an event. When a string is supplied from System.in, the method notifyObservers() is then called in order to notify all observers of the event's occurrence, in the form of an invocation of their update methods.

Java

import java.util.ArrayList; import java.util.List; import java.util.Scanner; interface Observer { void update(String event); } class EventSource { List<Observer> observers = new ArrayList<>(); public void notifyObservers(String event) { observers.forEach(observer -> 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 -> System.out.println("Received response: " + event)); eventSource.scanSystemIn(); } }

C++

This is a C++11 implementation.

#include <functional> #include <iostream> #include <list> class Subject; //Forward declaration for usage in Observer class Observer { public: explicit Observer(Subject& subj); virtual ~Observer(); Observer(const Observer&) = delete; // rule of three Observer& operator=(const Observer&) = delete; virtual void update( Subject& s) const = 0; private: // Reference to a Subject object to detach in the destructor Subject& subject; }; // Subject is the base class for event generation class Subject { public: using RefObserver = std::reference_wrapper<const Observer>; // Notify all the attached observers void notify() { for (const auto& x: observers) { x.get().update(*this); } } // Add an observer void attach(const Observer& observer) { observers.push_front(observer); } // Remove an observer void detach(Observer& observer) { observers.remove_if( [&observer ](const RefObserver& obj) { return &obj.get()==&observer; }); } private: std::list<RefObserver> observers; }; Observer::Observer(Subject& subj) : subject(subj) { subject.attach(*this); } Observer::~Observer() { subject.detach(*this); } // Example of usage class ConcreteObserver: public Observer { public: ConcreteObserver(Subject& subj) : Observer(subj) {} // Get notification void update(Subject&) const override { std::cout << "Got a notification" << std::endl; } }; int main() { Subject cs; ConcreteObserver co1(cs); ConcreteObserver co2(cs); cs.notify(); }

The program output is like

Got a notification Got a notification

Groovy

class EventSource { private observers = [] private notifyObservers(String event) { observers.each { it(event) } } void addObserver(observer) { observers += observer } void scanSystemIn() { var scanner = new Scanner(System.in) while (scanner) { var line = scanner.nextLine() notifyObservers(line) } } } println 'Enter Text: ' var eventSource = new EventSource() eventSource.addObserver { event -> println "Received response: $event" } eventSource.scanSystemIn()

Kotlin

import java.util.Scanner typealias Observer = (event: String) -> Unit; class EventSource { private var observers = mutableListOf<Observer>() private fun notifyObservers(event: String) { observers.forEach { it(event) } } fun addObserver(observer: Observer) { observers += observer } fun scanSystemIn() { val scanner = Scanner(System.`in`) while (scanner.hasNext()) { val line = scanner.nextLine() notifyObservers(line) } } } fun main(arg: List<String>) { println("Enter Text: ") val eventSource = EventSource() eventSource.addObserver { event -> println("Received response: $event") } eventSource.scanSystemIn() }

Delphi

uses System.Generics.Collections, System.SysUtils; type IObserver = interface ['{0C8F4C5D-1898-4F24-91DA-63F1DD66A692}'] procedure Update(const AValue: string); end; type TObserverManager = class private FObservers: TList<IObserver>; public constructor Create; overload; destructor Destroy; override; procedure NotifyObservers(const AValue: string); procedure AddObserver(const AObserver: IObserver); procedure UnregisterObsrver(const AObserver: IObserver); end; type TListener = class(TInterfacedObject, IObserver) private FName: string; public constructor Create(const AName: string); reintroduce; procedure Update(const AValue: string); end; procedure TObserverManager.AddObserver(const AObserver: IObserver); begin if not FObservers.Contains(AObserver) then FObservers.Add(AObserver); end; begin FreeAndNil(FObservers); inherited; end; procedure TObserverManager.NotifyObservers(const AValue: string); var i: Integer; begin for i := 0 to FObservers.Count - 1 do FObservers[i].Update(AValue); end; procedure TObserverManager.UnregisterObsrver(const AObserver: IObserver); begin if FObservers.Contains(AObserver) then FObservers.Remove(AObserver); end; constructor TListener.Create(const AName: string); begin inherited Create; FName := AName; end; procedure TListener.Update(const AValue: string); begin WriteLn(FName + ' listener received notification: ' + AValue); end; procedure TMyForm.ObserverExampleButtonClick(Sender: TObject); var LDoorNotify: TObserverManager; LListenerHusband: IObserver; LListenerWife: IObserver; begin LDoorNotify := TObserverManager.Create; try LListenerHusband := TListener.Create('Husband'); LDoorNotify.AddObserver(LListenerHusband); LListenerWife := TListener.Create('Wife'); LDoorNotify.AddObserver(LListenerWife); LDoorNotify.NotifyObservers('Someone is knocking on the door'); finally FreeAndNil(LDoorNotify); end; end;

Output

Husband listener received notification: Someone is knocking on the door Wife listener received notification: Someone is knocking on the door

Python

A similar example in Python:

class Observable: def __init__(self): self._observers = [] def register_observer(self, observer) -> None: self._observers.append(observer) def notify_observers(self, *args, **kwargs) -> None: for observer in self._observers: observer.notify(self, *args, **kwargs) class Observer: def __init__(self, observable): observable.register_observer(self) def notify(self, observable, *args, **kwargs) -> None: print("Got", args, kwargs, "From", observable) subject = Observable() observer = Observer(subject) subject.notify_observers("test", kw="python") # prints: Got ('test',) {'kw': 'python'} From <__main__.Observable object at 0x0000019757826FD0>

C#

C# provides the IObservable.6 and IObserver7 interfaces as well as documentation on how to implement the design pattern.8

class Payload { internal string Message { get; set; } } class Subject : IObservable<Payload> { private readonly ICollection<IObserver<Payload>> _observers = new List<IObserver<Payload>>(); IDisposable IObservable<Payload>.Subscribe(IObserver<Payload> 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<Payload> _observer; private readonly ICollection<IObserver<Payload>> _observers; internal Unsubscriber( IObserver<Payload> observer, ICollection<IObserver<Payload>> observers) { _observer = observer; _observers = observers; } void IDisposable.Dispose() { if (_observer != null && _observers.Contains(_observer)) { _observers.Remove(_observer); } } } internal class Observer : IObserver<Payload> { internal string Message { get; set; } public void OnCompleted() { } public void OnError(Exception error) { } public void OnNext(Payload value) { Message = value.Message; } internal IDisposable Register(IObservable<Payload> subject) { return subject.Subscribe(this); } }

JavaScript

JavaScript has a deprecated Object.observe function that was a more accurate implementation of the observer pattern.9 This would fire events upon change to the observed object. Without the deprecated Object.observe function, the pattern may be implemented with more explicit code:10

let Subject = { _state: 0, _observers: [], add: function(observer) { this._observers.push(observer); }, getState: function() { return this._state; }, setState: function(value) { this._state = value; for (let i = 0; i < this._observers.length; i++) { this._observers[i].signal(this); } } }; let Observer = { signal: function(subject) { let currentValue = subject.getState(); console.log(currentValue); } } Subject.add(Observer); Subject.setState(10); //Output in console.log - 10

See also

  • Observer implementations in various languages at Wikibooks

References

  1. Erich Gamma; Richard Helm; Ralph Johnson; John Vlissides (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley. pp. 293ff. ISBN 0-201-63361-2. 0-201-63361-2

  2. "Observer Design Pattern". www.geeksforgeeks.org. https://www.geeksforgeeks.org/observer-pattern-set-1-introduction/

  3. Comparison between different observer pattern implementations Moshe Bindler, 2015 (Github) https://github.com/millermedeiros/js-signals/wiki/Comparison-between-different-Observer-Pattern-implementations

  4. Differences between pub/sub and observer pattern The Observer Pattern by Adi Osmani (Safari books online) https://www.safaribooksonline.com/library/view/learning-javascript-design/9781449334840/ch09s05.html

  5. The Windows Programming Experience Charles Petzold, Nov 10, 1992, PC Magazine (Google Books) https://books.google.com/books?id=18wFKrkDdM0C&pg=PA230&lpg=PA230

  6. "IObservable Interface (System)". learn.microsoft.com. Retrieved 9 November 2024. https://learn.microsoft.com/en-us/dotnet/api/system.iobservable-1?view=net-8.0

  7. "IObserver Interface (System)". learn.microsoft.com. Retrieved 9 November 2024. https://learn.microsoft.com/en-us/dotnet/api/system.iobserver-1?view=net-8.0

  8. "Observer design pattern - .NET". learn.microsoft.com. 25 May 2023. Retrieved 9 November 2024. https://learn.microsoft.com/en-us/dotnet/standard/events/observer-design-pattern

  9. "jQuery - Listening for variable changes in JavaScript". https://stackoverflow.com/a/50862441/887092

  10. "Jquery - Listening for variable changes in JavaScript". https://stackoverflow.com/a/37403125/887092