2022-06-23 15:26:15 +01:00
|
|
|
---
|
2024-06-16 18:30:03 +01:00
|
|
|
tags:
|
|
|
|
- OOP
|
|
|
|
- design-patterns
|
2022-06-23 15:26:15 +01:00
|
|
|
---
|
|
|
|
|
2022-06-24 20:13:24 +01:00
|
|
|
# Observer pattern
|
2022-06-23 15:26:15 +01:00
|
|
|
|
|
|
|
The Observer design pattern is also known as the 'publish/subscribe' pattern.
|
|
|
|
|
2024-02-02 15:58:13 +00:00
|
|
|
> 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.
|
2022-06-23 15:26:15 +01:00
|
|
|
|
2024-02-02 15:58:13 +00:00
|
|
|
The observer pattern instantiates a **one-to-many** relationship between the
|
|
|
|
subject and its observers: when one object updates, it notifies many other
|
|
|
|
objects that it has been updated.
|
2022-06-23 15:26:15 +01:00
|
|
|
|
2024-02-02 15:58:13 +00:00
|
|
|
This is another design pattern that is useful when implementing a global state.
|
|
|
|
When the subject updates its subjects must follow suit and adapt to its changes.
|
|
|
|
Here the subject is the instrument for maintaining the global state.
|
2022-06-23 15:26:15 +01:00
|
|
|
|
|
|
|
## Subject class
|
|
|
|
|
2024-02-02 15:58:13 +00:00
|
|
|
This class maintains a list of observers that will be notified when it is
|
|
|
|
updated. It should have the following attributes:
|
2022-06-23 15:26:15 +01:00
|
|
|
|
|
|
|
- array of existing observers
|
|
|
|
- an `addObserver` method which pushes an observer onto the observers array
|
|
|
|
- a `removeObserver` method that does the opposite
|
|
|
|
- a `notify` method that broadcasts to the observers that a change has happened
|
|
|
|
|
|
|
|
## Observer class
|
|
|
|
|
2024-02-02 15:58:13 +00:00
|
|
|
Observers must implement an `update` method that will be called by the subject's
|
|
|
|
`notify` method.
|
2022-06-23 15:26:15 +01:00
|
|
|
|
|
|
|
## Example
|
|
|
|
|
|
|
|
```js
|
|
|
|
class Subject {
|
|
|
|
observers = [];
|
|
|
|
|
|
|
|
getCurrentTime() {
|
|
|
|
var d = new Date();
|
|
|
|
return `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
addObserver(...observer) {
|
|
|
|
for (const o of observer) {
|
|
|
|
this.observers.push(o);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
removeObserver(observer) {
|
|
|
|
const match = this.observers.findIndex((element) => element === observer);
|
|
|
|
this.observers.splice(match, 1);
|
|
|
|
}
|
|
|
|
notify() {
|
|
|
|
for (const o of this.observers) {
|
|
|
|
o.update(`I was updated at ${this.getCurrentTime()}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class ObserverA {
|
2024-02-02 15:58:13 +00:00
|
|
|
state = "I am observer A";
|
2022-06-23 15:26:15 +01:00
|
|
|
update(newState) {
|
|
|
|
this.state = newState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class ObserverB {
|
2024-02-02 15:58:13 +00:00
|
|
|
state = "I am observer B";
|
2022-06-23 15:26:15 +01:00
|
|
|
|
|
|
|
update(newState) {
|
|
|
|
this.state = newState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let subjectInstance = new Subject();
|
|
|
|
let obsAInstance = new ObserverA();
|
|
|
|
let obsBInstance = new ObserverB();
|
|
|
|
|
|
|
|
subjectInstance.addObserver(obsAInstance, obsBInstance);
|
|
|
|
|
|
|
|
subjectInstance.notify();
|
|
|
|
console.log(obsBInstance.state);
|
|
|
|
```
|