Observer pattern


The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
It is mainly used to implement distributed event handling systems, in "event driven" software. In those systems, the subject is usually called a "stream of events" or "stream source of events", while the observers are called "sink of events". The stream nomenclature simulates or adapts to a physical setup where the observers are physically separated and have no control over the emitted events of the subject/stream-source. This pattern then perfectly suits any process where data arrives through I/O, that is, where data is not available to the CPU at startup, but can arrive "randomly". Most modern languages have built-in "event" constructs which implement the observer pattern components. While not mandatory most 'observers' implementations will use background threads listening for subject events and other support mechanism from the kernel

Overview

The Observer design pattern is one of the twenty-three well-known "Gang of Four" design patterns that describe how to solve recurring design problems to design flexible and reusable object-oriented software, that is, objects that are easier to implement, change, test, and reuse.

What problems can the Observer design pattern solve?

The Observer pattern addresses the following problems:
Defining a one-to-many dependency between objects by defining one object that updates the state of dependent objects directly is inflexible
because it couples the subject to particular dependent objects. Still it can make sense from a performance point of view or if the object implementation is tightly coupled.
Tightly coupled objects can be hard to implement in some scenarios, and hard to reuse because they refer to and know about many different objects with different interfaces.
In other scenarios tightly coupled objects can be a better option since the compiler will be able to detect errors at compile time and optimize the code at CPU instruction level.

What solution does the Observer design pattern describe?

The sole responsibility of a subject is to maintain a list of observers and to notify them of state changes by calling their update operation.
The responsibility of observers is to register themselves on a subject and to update their 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.
See also the UML class and sequence diagram below.

Strong vs. weak reference

The observer pattern can cause memory leaks, known as the lapsed listener problem, because in 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 by the subject holding weak references to the observers.

Coupling and typical pub-sub implementations

Typically, the observer pattern is implemented so the "subject" being "observed" is part of the object for which state changes are being observed. 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, the lack of flexibility in conditional dispersion, and possible hindrance to desired security measures. In some implementations of the publish-subscribe pattern, this is solved by creating a dedicated "message queue" server 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" knowing only about the expected message, while knowing nothing about the message sender itself; the sender also may 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 at all.
In early implementations of multi-window operating systems like OS/2 and Windows, the terms "publish-subscribe pattern" and "event driven software development" were used as a synonym for the observer pattern.
The observer pattern, as described in the GoF book, is a very basic concept and does not address removing interest in changes to the observed "subject" or special logic to be done by the observed "subject" before or after notifying the observers. The pattern also does not deal with recording when change notifications are sent or guaranteeing that they are being received. These concerns are typically handled in message queueing systems of which the observer pattern is only a small part.
Related patterns: Publish–subscribe pattern, mediator, singleton.

Uncoupled

The observer pattern may be used in the absence of publish-subscribe, as in the case where model status is frequently updated. Frequent updates may cause the view to become unresponsive ; such observers should instead use a timer. Thus instead of being 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, where the underlying operation's progress changes with several times per second.

Structure

UML class and sequence diagram

In the above UML class diagram, the Subject class does not update the state of dependent objects directly.
Instead, Subject refers to the Observer interface 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 run-time interactions: The Observer1 and Observer2 objects call attach 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 Observer2
objects, which request the changed data from Subject1 to update their state.

UML class diagram

Example

While the library classes and 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 treats 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.List;
import java.util.ArrayList;
import java.util.Scanner;
class EventSource


public class ObserverDemo

Kotlin


import java.util.Scanner
typealias Observer = -> Unit;
class EventSource


fun main

Delphi


uses
System.Generics.Collections
, System.SysUtils
;
type
IObserver = interface

procedure Update;
end;
type
TEdijsObserverManager = class
strict private
FObservers: TList;
public
constructor Create; overload;
destructor Destroy; override;
procedure NotifyObservers;
procedure AddObserver;
procedure UnregisterObsrver;
end;
type
TListener = class
strict private
FName: string;
public
constructor Create; reintroduce;
procedure Update;
end;
procedure TEdijsObserverManager.AddObserver;
begin
if not FObservers.Contains then
FObservers.Add;
end;
constructor TEdijsObserverManager.Create;
begin
inherited Create;
FObservers := TList.Create;
end;
destructor TEdijsObserverManager.Destroy;
begin
FreeAndNil;
inherited;
end;
procedure TEdijsObserverManager.NotifyObservers;
var
i: Integer;
begin
for i := 0 to FObservers.Count - 1 do
FObservers.Update;
end;
procedure TEdijsObserverManager.UnregisterObsrver;
begin
if FObservers.Contains then
FObservers.Remove;
end;
constructor TListener.Create;
begin
inherited Create;
FName := AName;
end;
procedure TListener.Update;
begin
WriteLn;
end;
procedure TEdijsForm.ObserverExampleButtonClick;
var
_DoorNotify: TEdijsObserverManager;
_ListenerHusband: IObserver;
_ListenerWife: IObserver;
begin
_DoorNotify := TEdijsObserverManager.Create;
try
_ListenerHusband := TListener.Create;
_DoorNotify.AddObserver;
_ListenerWife := TListener.Create;
_DoorNotify.AddObserver;
_DoorNotify.NotifyObservers;
finally
FreeAndNil;
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._observers =

def register_observer:
self._observers.append

def notify_observers:
for observer in self._observers:
observer.notify
class Observer:
def __init__:
observable.register_observer

def notify:
print
subject = Observable
observer = Observer
subject.notify_observers

C#


public class Payload



public class Subject : IObservable



public class Unsubscriber : IDisposable



public class Observer : IObserver

JavaScript

Libraries and frameworks exist for JavaScript to utilize the observer pattern. One such library is seen below.

// import the fromEvent operator
import from 'rxjs';
// grab button reference
const button = document.getElementById;
// create an observable of button clicks
const myObservable = fromEvent;
// for now, let's just log the event on each click
const subscription = myObservable.subscribe;