90 lines
2.2 KiB
Markdown
90 lines
2.2 KiB
Markdown
![]() |
---
|
||
|
tags:
|
||
|
- OOP
|
||
|
- design-patterns
|
||
|
---
|
||
|
|
||
|
# Observer pattern
|
||
|
|
||
|
The Observer design pattern is also known as the 'publish/subscribe' 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.
|
||
|
|
||
|
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.
|
||
|
|
||
|
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.
|
||
|
|
||
|
## Subject class
|
||
|
|
||
|
This class maintains a list of observers that will be notified when it is
|
||
|
updated. It should have the following attributes:
|
||
|
|
||
|
- 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
|
||
|
|
||
|
Observers must implement an `update` method that will be called by the subject's
|
||
|
`notify` method.
|
||
|
|
||
|
## 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 {
|
||
|
state = "I am observer A";
|
||
|
update(newState) {
|
||
|
this.state = newState;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class ObserverB {
|
||
|
state = "I am observer B";
|
||
|
|
||
|
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);
|
||
|
```
|