Observer pattern: Difference between revisions

From Wikipedia, the free encyclopedia
Jump to navigation Jump to search
imported>John of Reading
m C++: Typo fixing, replaced: obsevers → observers
 
imported>Frap
 
Line 1: Line 1:
{{Short description|Software design pattern based on an event-updated object with a list of dependents}}
{{Short description|Software design pattern based on an event-updated object with a list of dependents}}


In [[software design]] and [[Software engineering|engineering]], the '''observer pattern''' is a [[software design pattern]] in which an [[Object (computer science)#Objects in object-oriented programming|object]], named the '''''subject''''', maintains a list of its dependents, called '''''observers''''', and notifies them automatically of any [[Event (computing)|state changes]], usually by calling one of their [[Method (computer science)|methods]].
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 (computer science)|state changes]], typically by calling one of their [[method (computer science)|methods]]. The subject knows its observers through a standardized interface and manages the subscription list directly.


It is often used for implementing distributed [[event handling|event-handling]] systems in [[Event-driven programming|event-driven software]]. In such systems, the subject is usually named a "stream of events" or "stream source of events" while the observers are called "sinks of events." The stream nomenclature alludes to a physical setup in which the observers are physically separated and have no control over the emitted events from the subject/stream source. This pattern thus suits any process by which data arrives from some input that is not available to the [[CPU]] at [[Booting|startup]], but instead may arrive at arbitrary or indeterminate times ([[HTTP request]]s, [[GPIO]] data, [[user input]] from [[peripheral]]s and [[distributed database]]s, etc.).
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 request]]s, [[general-purpose input/output|GPIO]] signals, updates from [[distributed database]]s, or changes in a [[graphical user interface|GUI]] model.


==Overview==
==Overview==
The observer design pattern is a behavioural pattern listed among the 23 well-known [[Design Patterns|"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.<ref name="GoF">{{cite book|author=Erich Gamma|url=https://archive.org/details/designpatternsel00gamm/page/293|title=Design Patterns: Elements of Reusable Object-Oriented Software|last2=Richard Helm|last3=Ralph Johnson|last4=John Vlissides|publisher=Addison Wesley|year=1994|isbn=0-201-63361-2|pages=[https://archive.org/details/designpatternsel00gamm/page/293 293ff]|url-access=registration}}</ref>


The observer design pattern is a behavioural pattern listed among the 23 well-known [[Design Patterns|"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.<ref name="GoF">{{cite book|author=Erich Gamma|url=https://archive.org/details/designpatternsel00gamm/page/293|title=Design Patterns: Elements of Reusable Object-Oriented Software|last2=Richard Helm|last3=Ralph Johnson|last4=John Vlissides|publisher=Addison Wesley|year=1994|isbn=0-201-63361-2|pages=[https://archive.org/details/designpatternsel00gamm/page/293 293ff]|url-access=registration}}</ref>
The observer pattern addresses the following requirements:<ref>{{cite web |title=Observer Design Pattern |url=https://www.geeksforgeeks.org/observer-pattern-set-1-introduction/ |access-date= |website=www.geeksforgeeks.org}}</ref>


The observer pattern addresses the following problems:<ref>{{cite web |title=Observer Design Pattern |url=https://www.geeksforgeeks.org/observer-pattern-set-1-introduction/ |access-date= |website=www.geeksforgeeks.org}}</ref>
* A one-to-many dependency between objects should be defined without making the objects tightly coupled.
* 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.
* When one object changes state, an open-ended number of dependent objects should be updated automatically.
* An object can notify multiple other objects.
* An object can notify multiple other objects.


Defining a one-to-many dependency between objects by defining one object (subject) that updates the state of dependent objects directly is inflexible because it couples the subject to particular dependent objects. However, it might be applicable from a performance point of view or if the object implementation is tightly coupled (such as low-level kernel structures that execute thousands of times per second). Tightly coupled objects can be difficult to implement in some scenarios and are not easily reused because they refer to and are aware of many objects with different interfaces. In other scenarios, tightly coupled objects can be a better option because the compiler is able to detect errors at compile time and optimize the code at the CPU instruction level.
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:
 
# Define <code>Subject</code> and <code>Observer</code> objects with standardized interfaces.
# When a subject changes state, all registered observers are notified and updated automatically.
# The subject manages its own state while also maintaining a list of observers and notifying them of state changes by calling their <code>update()</code> operation.
# 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 <code>update()</code> method—it has no knowledge of observers' concrete types or internal implementation details. Observers can be added and removed independently at run time.
 
== Relationship to publish–subscribe ==
The observer pattern and the [[publish–subscribe pattern]] are closely related and often confused, as both support one-to-many communication between components. However, they differ significantly in architecture, degree of coupling, and common use cases.
 
The table below summarizes the key differences:
{| class="wikitable"
!Feature
!'''Observer Pattern'''
!'''Publish–Subscribe Pattern'''
|-
|'''Coupling'''
|''Tightly coupled'' — the subject holds direct references to its observers via a standardized interface.
|''Loosely coupled'' — publishers and subscribers are unaware of each other.
|-
|'''Communication'''
|''Direct'' — the subject calls observer methods, typically synchronously.
|''Indirect'' — a broker (message bus or event manager) dispatches messages to subscribers.
|-
|'''Knowledge of Participants'''
|The subject knows its observers.
|Publisher and subscriber are decoupled; neither knows about the other.
|-
|'''Scalability'''
|Suitable for in-process systems like GUI toolkits.
|More scalable; supports distributed systems and asynchronous messaging.
|-
|'''Synchronous or Asynchronous'''
|Typically synchronous but can be asynchronous with event queues.
|Typically asynchronous but can be synchronous.
|-
|'''Filtering'''
|Limited — observers receive all events and filter internally.
|Rich filtering — brokers may filter by topic, content, or rules.
|-
|'''Fault Tolerance'''
|Observer failures can affect the subject.
|Failures are isolated; the broker decouples participants.
|-
|'''Typical Usage'''
|GUI frameworks, MVC architecture, local object notifications.
|Microservices, distributed systems, messaging middleware.
|}
In practice, publish–subscribe systems evolved to address several limitations of the observer pattern. A typical observer implementation creates a tight coupling between the subject and its observers. This may limit scalability, flexibility, and maintainability, especially in distributed environments. Subjects and observers must conform to a shared interface, and both parties are aware of each other’s presence.


* Define <code>Subject</code> and <code>Observer</code> objects.
To reduce this coupling, publish–subscribe systems introduce a message broker or event bus that intermediates between publishers and subscribers. This additional layer removes the need for direct references, allowing systems to evolve independently. Brokers may also support features like message persistence, delivery guarantees, topic-based filtering, and asynchronous communication.
* When a subject changes state, all registered observers are notified and updated automatically (and probably asynchronously).


The sole responsibility of a subject is to maintain a list of observers and to notify them of state changes by calling their <code>update()</code> operation. 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 their state with the subject's state) when they are notified. This makes subject and observers loosely coupled. Subject and observers have no explicit knowledge of each other. Observers can be added and removed independently at run time. This notification-registration interaction is also known as [[publish-subscribe]].
In some systems, the observer pattern is used internally to implement subscription mechanisms behind a publish–subscribe interface. In other cases, the patterns are applied independently. For example, [[JavaScript]] libraries and frameworks often offer both observer-like subscriptions (e.g., via callback registration) and decoupled pub-sub mechanisms (e.g., via event emitters or signals).<ref>[https://github.com/millermedeiros/js-signals/wiki/Comparison-between-different-Observer-Pattern-implementations Comparison between different observer pattern implementations] — Moshe Bindler, 2015 (GitHub)</ref><ref>[https://www.safaribooksonline.com/library/view/learning-javascript-design/9781449334840/ch09s05.html Differences between pub/sub and observer pattern] — ''The Observer Pattern'' by Adi Osmani (Safari Books Online)</ref>


== Strong vs. weak reference ==
Historically, in early graphical operating systems like [[OS/2]] and [[Microsoft Windows]], the terms "publish–subscribe" and "event-driven programming" were often used as synonyms for the observer pattern.<ref>[https://books.google.com/books?id=18wFKrkDdM0C&pg=PA230 The Windows Programming Experience], [[Charles Petzold]], November 10, 1992, ''PC Magazine'' ([[Google Books]])</ref>


The observer pattern can cause [[memory leak]]s, 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 reference]]s to the observers.
The observer pattern, as formalized in ''Design Patterns'',<ref name="GoF2" /> deliberately omits concerns such as unsubscription, notification filtering, delivery guarantees, and message logging. These advanced capabilities are typically implemented in robust message queuing systems, where the observer pattern may serve as a foundational mechanism but is not sufficient by itself.


== Coupling and typical publish-subscribe implementations ==
Related patterns include [[Mediator pattern|mediator]] and [[Singleton pattern|singleton]].
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 [[Coupling (computer programming)|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 ([[polling (computer science)|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.<ref>[https://github.com/millermedeiros/js-signals/wiki/Comparison-between-different-Observer-Pattern-implementations Comparison between different observer pattern implementations] Moshe Bindler, 2015 (Github)</ref><ref>[https://www.safaribooksonline.com/library/view/learning-javascript-design/9781449334840/ch09s05.html Differences between pub/sub and observer pattern] The Observer Pattern by Adi Osmani (Safari books online)</ref>


In early implementations of multi-window operating systems such as [[OS/2]] and [[Microsoft Windows|Windows]], the terms "publish-subscribe pattern" and "event-driven software development" were used as synonyms for the observer pattern.<ref>[https://books.google.com/books?id=18wFKrkDdM0C&pg=PA230&lpg=PA230 The Windows Programming Experience] [[Charles Petzold]], Nov 10, 1992, [[PC Magazine]] ([[Google Books]])</ref>
== Limitations and solutions ==


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.  
=== Strong vs. weak references ===
A common drawback of the observer pattern is the potential for [[memory leak]]s, known as the [[lapsed listener problem]]. This occurs when a subject maintains strong references to its observers, preventing them from being [[Garbage collection (computer science)|garbage collected]] even if they are no longer needed elsewhere. Because the pattern typically requires both explicit registration and deregistration (as in the [[dispose pattern]]), forgetting to unregister observers can leave dangling references. This issue can be mitigated by using [[weak reference]]s for observer references, allowing the garbage collector to reclaim observer objects that are no longer in use.


Related patterns include publish–subscribe, [[mediator pattern|mediator]] and [[singleton pattern|singleton]].
=== Throttling and temporal decoupling ===
In some applications, particularly user interfaces, the subject's state may change so frequently that notifying observers on every change is inefficient or counterproductive. For example, a view that re-renders on every minor change in a data model might become unresponsive or flicker.


===Uncoupled===
In such cases, the observer pattern can be modified to decouple notifications ''temporally'' by introducing a throttling mechanism, such as a timer. Rather than updating on every state change, the observer polls the subject or is notified at regular intervals, rendering an approximate but stable view of the model.
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 [[painter's algorithm|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 bar|progress bars]], in which the underlying operation's progress changes frequently.
 
This approach is commonly used for elements like [[Progress bar|progress bars]], where the underlying process changes state rapidly. Instead of responding to every minor increment, the observer updates the visual display periodically, improving performance and usability.
 
This form of temporal decoupling allows observers to remain responsive without being overwhelmed by high-frequency updates, while still reflecting the overall trend or progress of the subject’s state.


==Structure==
==Structure==
Line 95: Line 151:


         eventSource.scanSystemIn();
         eventSource.scanSystemIn();
    }
}
</syntaxhighlight>
===C#===
C# provides the {{Code|IObservable}}.<ref>{{cite web |title=IObservable Interface (System) |url=https://learn.microsoft.com/en-us/dotnet/api/system.iobservable-1?view=net-8.0 |website=learn.microsoft.com |access-date=9 November 2024 |language=en-us}}</ref> and {{Code|IObserver}}<ref>{{cite web |title=IObserver Interface (System) |url=https://learn.microsoft.com/en-us/dotnet/api/system.iobserver-1?view=net-8.0 |website=learn.microsoft.com |access-date=9 November 2024 |language=en-us}}</ref> interfaces as well as documentation on how to implement the design pattern.<ref>{{cite web |title=Observer design pattern - .NET |url=https://learn.microsoft.com/en-us/dotnet/standard/events/observer-design-pattern |website=learn.microsoft.com |access-date=9 November 2024 |language=en-us |date=25 May 2023}}</ref>
<syntaxhighlight lang="csharp">
class Payload
{
    internal string Message { get; init; }
}
class Subject : IObservable<Payload>
{
    private readonly List<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>
{
    private string _message;
    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);
     }
     }
}
}
Line 368: Line 501:
         self._observers = []
         self._observers = []


     def register_observer(self, observer) -> None:
     def register_observer(self, observer: Observer) -> None:
         self._observers.append(observer)
         self._observers.append(observer)


Line 377: Line 510:


class Observer:
class Observer:
     def __init__(self, observable):
     def __init__(self, observable: Observable):
         observable.register_observer(self)
         observable.register_observer(self)


     def notify(self, observable, *args, **kwargs) -> None:
     def notify(self, observable: Observable, *args, **kwargs) -> None:
         print("Got", args, kwargs, "From", observable)
         print("Got", args, kwargs, "From", observable)


Line 389: Line 522:


# prints: Got ('test',) {'kw': 'python'} From <__main__.Observable object at 0x0000019757826FD0>
# prints: Got ('test',) {'kw': 'python'} From <__main__.Observable object at 0x0000019757826FD0>
</syntaxhighlight>
===C#===
C# provides the {{Code|IObservable}}.<ref>{{cite web |title=IObservable Interface (System) |url=https://learn.microsoft.com/en-us/dotnet/api/system.iobservable-1?view=net-8.0 |website=learn.microsoft.com |access-date=9 November 2024 |language=en-us}}</ref> and {{Code|IObserver}}<ref>{{cite web |title=IObserver Interface (System) |url=https://learn.microsoft.com/en-us/dotnet/api/system.iobserver-1?view=net-8.0 |website=learn.microsoft.com |access-date=9 November 2024 |language=en-us}}</ref> interfaces as well as documentation on how to implement the design pattern.<ref>{{cite web |title=Observer design pattern - .NET |url=https://learn.microsoft.com/en-us/dotnet/standard/events/observer-design-pattern |website=learn.microsoft.com |access-date=9 November 2024 |language=en-us |date=25 May 2023}}</ref>
<syntaxhighlight lang="csharp">
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);
    }
}
</syntaxhighlight>
</syntaxhighlight>


Line 472: Line 528:
JavaScript has a deprecated {{code|Object.observe}} function that was a more accurate implementation of the observer pattern.<ref>{{Cite web|url=https://stackoverflow.com/a/50862441/887092|title = jQuery - Listening for variable changes in JavaScript}}</ref> This would fire events upon change to the observed object. Without the deprecated {{code|Object.observe}} function, the pattern may be implemented with more explicit code:<ref>{{Cite web|url=https://stackoverflow.com/a/37403125/887092|title = Jquery - Listening for variable changes in JavaScript}}</ref>
JavaScript has a deprecated {{code|Object.observe}} function that was a more accurate implementation of the observer pattern.<ref>{{Cite web|url=https://stackoverflow.com/a/50862441/887092|title = jQuery - Listening for variable changes in JavaScript}}</ref> This would fire events upon change to the observed object. Without the deprecated {{code|Object.observe}} function, the pattern may be implemented with more explicit code:<ref>{{Cite web|url=https://stackoverflow.com/a/37403125/887092|title = Jquery - Listening for variable changes in JavaScript}}</ref>


<syntaxhighlight lang="js">
<syntaxhighlight lang="javascript">
let Subject = {
let Subject = {
     _state: 0,
     _state: 0,
Line 500: Line 556:
Subject.add(Observer);
Subject.add(Observer);
Subject.setState(10);
Subject.setState(10);
//Output in console.log - 10
// Output in console.log - 10
</syntaxhighlight>
</syntaxhighlight>



Latest revision as of 20:08, 11 June 2025

Template:Short description

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.

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.

Relationship to publish–subscribe

The observer pattern and the publish–subscribe pattern are closely related and often confused, as both support one-to-many communication between components. However, they differ significantly in architecture, degree of coupling, and common use cases.

The table below summarizes the key differences:

Feature Observer Pattern Publish–Subscribe Pattern
Coupling Tightly coupled — the subject holds direct references to its observers via a standardized interface. Loosely coupled — publishers and subscribers are unaware of each other.
Communication Direct — the subject calls observer methods, typically synchronously. Indirect — a broker (message bus or event manager) dispatches messages to subscribers.
Knowledge of Participants The subject knows its observers. Publisher and subscriber are decoupled; neither knows about the other.
Scalability Suitable for in-process systems like GUI toolkits. More scalable; supports distributed systems and asynchronous messaging.
Synchronous or Asynchronous Typically synchronous but can be asynchronous with event queues. Typically asynchronous but can be synchronous.
Filtering Limited — observers receive all events and filter internally. Rich filtering — brokers may filter by topic, content, or rules.
Fault Tolerance Observer failures can affect the subject. Failures are isolated; the broker decouples participants.
Typical Usage GUI frameworks, MVC architecture, local object notifications. Microservices, distributed systems, messaging middleware.

In practice, publish–subscribe systems evolved to address several limitations of the observer pattern. A typical observer implementation creates a tight coupling between the subject and its observers. This may limit scalability, flexibility, and maintainability, especially in distributed environments. Subjects and observers must conform to a shared interface, and both parties are aware of each other’s presence.

To reduce this coupling, publish–subscribe systems introduce a message broker or event bus that intermediates between publishers and subscribers. This additional layer removes the need for direct references, allowing systems to evolve independently. Brokers may also support features like message persistence, delivery guarantees, topic-based filtering, and asynchronous communication.

In some systems, the observer pattern is used internally to implement subscription mechanisms behind a publish–subscribe interface. In other cases, the patterns are applied independently. For example, JavaScript libraries and frameworks often offer both observer-like subscriptions (e.g., via callback registration) and decoupled pub-sub mechanisms (e.g., via event emitters or signals).[3][4]

Historically, in early graphical operating systems like OS/2 and Microsoft Windows, the terms "publish–subscribe" and "event-driven programming" were often used as synonyms for the observer pattern.[5]

The observer pattern, as formalized in Design Patterns,[6] deliberately omits concerns such as unsubscription, notification filtering, delivery guarantees, and message logging. These advanced capabilities are typically implemented in robust message queuing systems, where the observer pattern may serve as a foundational mechanism but is not sufficient by itself.

Related patterns include mediator and singleton.

Limitations and solutions

Strong vs. weak references

A common drawback of the observer pattern is the potential for memory leaks, known as the lapsed listener problem. This occurs when a subject maintains strong references to its observers, preventing them from being garbage collected even if they are no longer needed elsewhere. Because the pattern typically requires both explicit registration and deregistration (as in the dispose pattern), forgetting to unregister observers can leave dangling references. This issue can be mitigated by using weak references for observer references, allowing the garbage collector to reclaim observer objects that are no longer in use.

Throttling and temporal decoupling

In some applications, particularly user interfaces, the subject's state may change so frequently that notifying observers on every change is inefficient or counterproductive. For example, a view that re-renders on every minor change in a data model might become unresponsive or flicker.

In such cases, the observer pattern can be modified to decouple notifications temporally by introducing a throttling mechanism, such as a timer. Rather than updating on every state change, the observer polls the subject or is notified at regular intervals, rendering an approximate but stable view of the model.

This approach is commonly used for elements like progress bars, where the underlying process changes state rapidly. Instead of responding to every minor increment, the observer updates the visual display periodically, improving performance and usability.

This form of temporal decoupling allows observers to remain responsive without being overwhelmed by high-frequency updates, while still reflecting the overall trend or progress of the subject’s state.

Structure

UML class and sequence diagram

File:W3sDesign Observer Design Pattern UML.jpg
A sample UML class and sequence diagram for the observer design pattern. [7]

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

File:Observer w update.svg
UML class diagram of Observer pattern

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#

C# provides the IObservable.[8] and IObserver[9] interfaces as well as documentation on how to implement the design pattern.[10]

class Payload
{
    internal string Message { get; init; }
}

class Subject : IObservable<Payload>
{
    private readonly List<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>
{
    private string _message;

    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);
    }
}

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: 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):
        observable.register_observer(self)

    def notify(self, observable: 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>

JavaScript

JavaScript has a deprecated Object.observe function that was a more accurate implementation of the observer pattern.[11] 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:[12]

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

References

Template:Reflist

External links

Template:Design Patterns Patterns

  1. Script error: No such module "citation/CS1".
  2. Script error: No such module "citation/CS1".
  3. Comparison between different observer pattern implementations — Moshe Bindler, 2015 (GitHub)
  4. Differences between pub/sub and observer patternThe Observer Pattern by Adi Osmani (Safari Books Online)
  5. The Windows Programming Experience, Charles Petzold, November 10, 1992, PC Magazine (Google Books)
  6. Cite error: Invalid <ref> tag; no text was provided for refs named GoF2
  7. Script error: No such module "citation/CS1".
  8. Script error: No such module "citation/CS1".
  9. Script error: No such module "citation/CS1".
  10. Script error: No such module "citation/CS1".
  11. Script error: No such module "citation/CS1".
  12. Script error: No such module "citation/CS1".