Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Observer pattern
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
{{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]]. 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.). ==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 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. * When one object changes state, an open-ended number of dependent objects should be updated automatically. * 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. * Define <code>Subject</code> and <code>Observer</code> objects. * 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]]. == Strong vs. weak reference == 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. == 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 [[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> 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 pattern|mediator]] and [[singleton pattern|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 [[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. ==Structure== ===UML class and sequence diagram=== [[File:w3sDesign Observer Design Pattern UML.jpg|frame|none|A sample UML class and sequence diagram for the observer design pattern. <ref>{{cite web|title=The Observer design pattern - Structure and Collaboration|url=http://w3sdesign.com/?gr=b07&ugr=struct|website=w3sDesign.com|access-date=2017-08-12}}</ref>]] In this [[Unified Modeling Language|UML]] [[class diagram]], the <code>Subject</code> class does not update the state of dependent objects directly. Instead, <code>Subject</code> refers to the <code>Observer</code> interface (<code>update()</code>) for updating state, which makes the <code>Subject</code> independent of how the state of dependent objects is updated. The <code>Observer1</code> and <code>Observer2</code> classes implement the <code>Observer</code> interface by synchronizing their state with subject's state. The [[Unified Modeling Language|UML]] [[sequence diagram]] shows the runtime interactions: The <code>Observer1</code> and <code>Observer2</code> objects call <code>attach(this)</code> on <code>Subject1</code> to register themselves. Assuming that the state of <code>Subject1</code> changes, <code>Subject1</code> calls <code>notify()</code> on itself. <code>notify()</code> calls <code>update()</code> on the registered <code>Observer1</code> and <code>Observer2</code>objects, which request the changed data (<code>getState()</code>) from <code>Subject1</code> to update (synchronize) their state. ===UML class diagram=== [[File:Observer w update.svg|none|thumb|500x500px|[[Unified Modeling Language|UML]] class diagram of Observer pattern]] ==Example== <!-- Wikipedia is not a list of examples. Do not add examples from your favorite programming language here; this page exists to explain the design pattern, not to show how it interacts with subtleties of every language under the sun. Feel free to add examples here: http://en.wikibooks.org/wiki/Computer_Science_Design_Patterns/Observer --> While the library classes [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Observer.html <code>java.util.Observer</code>] and [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Observable.html <code>java.util.Observable</code>] exist, they have been [[Deprecation|deprecated]] in Java 9 because the model implemented was quite limited. Below is an example written in [[Java (programming language)|Java]] that takes keyboard input and handles each input line as an event. When a string is supplied from <code>System.in</code>, the method <code>notifyObservers()</code> 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=== <syntaxhighlight lang="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(); } } </syntaxhighlight> ===C++=== This is a C++11 implementation. <syntaxhighlight lang="c++"> #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(); } </syntaxhighlight> The program output is like <syntaxhighlight lang="c++"> Got a notification Got a notification </syntaxhighlight> ===Groovy=== <syntaxhighlight lang="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() </syntaxhighlight> ===Kotlin=== <syntaxhighlight lang="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) } } } </syntaxhighlight> <syntaxhighlight lang="kotlin"> fun main(arg: List<String>) { println("Enter Text: ") val eventSource = EventSource() eventSource.addObserver { event -> println("Received response: $event") } eventSource.scanSystemIn() } </syntaxhighlight> ===Delphi=== <syntaxhighlight lang="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; </syntaxhighlight> Output <pre> Husband listener received notification: Someone is knocking on the door Wife listener received notification: Someone is knocking on the door </pre> ===Python=== A similar example in [[Python_(programming_language)|Python]]: <syntaxhighlight lang="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> </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> ===JavaScript=== 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"> 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 </syntaxhighlight> ==See also== *[[Implicit invocation]] *[[Client–server model]] *The observer pattern is often used in the [[entity–component–system]] pattern ==References== {{Reflist}} ==External links== *{{Wikibooks-inline|Computer Science Design Patterns|Observer|Observer implementations in various languages}} {{Design Patterns Patterns}} [[Category:Software design patterns]] [[Category:Articles with example Java code]] [[Category:Articles with example Python (programming language) code]] [[Category:Articles with example C Sharp code]]
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)
Pages transcluded onto the current version of this page
(
help
)
:
Template:Cite book
(
edit
)
Template:Cite web
(
edit
)
Template:Code
(
edit
)
Template:Design Patterns Patterns
(
edit
)
Template:Reflist
(
edit
)
Template:Short description
(
edit
)
Template:Wikibooks-inline
(
edit
)