Skip to main content

Observer

Observer is a behavioral design pattern also known as Publish-Subscribe which allows one object to notify muliple objects about events or state changes.

interface Publisher {
subscribe(observer: Observer): void
unsubscribe(observer: Observer): void
notify(): void
}

interface Observer {
update(publisher: Publisher): void
getId(): string
}

class Timer implements Publisher {
private observers: Observer[] = [];
time = 0

subscribe(observer: Observer): void {
const isExist = this.observers.filter(existObserver => existObserver.getId() === observer.getId())[0];

if (isExist) {
console.log('Observer has been subscribed already.');
return
}

this.observers.push(observer);
};

//unSubscribe an observer from the Publisher.
unsubscribe(observer: Observer): void {
const observerIndex = this.observers.findIndex(existObserver => existObserver.getId() === observer.getId());
if (observerIndex === -1) {
console.log('Nonexistent observer.');
return
}

this.observers.splice(observerIndex, 1);
};

// Notify all observers about an event.
notify(): void {
for (const observer of this.observers) {
observer.update(this);
}
};

tick() {
this.time++
this.notify()
}
}

class DigitalClock implements Observer {
private timer: Timer
private displayTime = 0
private id: string


constructor(timer: Timer) {
this.timer = timer
this.id = "randomId1"
this.timer.subscribe(this)
this.setDisplayTime(this.timer.time)
}

getId() {
return this.id
}

setDisplayTime(time: number){
this.displayTime = time
}

show(){
console.log("Digital Clock:", this.displayTime)
}

update(timer: Timer): void {
this.setDisplayTime(timer.time)
this.show()
}

unsubscribe(){
this.timer.unsubscribe(this)
}
}

class AnalogClock implements Observer {
private timer: Timer
private displayTime = 0
private id: string


constructor(timer: Timer) {
this.timer = timer
this.id = "randomId2"
this.timer.subscribe(this)
this.setDisplayTime(this.timer.time)
}

getId() {
return this.id
}

setDisplayTime(time: number){
this.displayTime = time
}

show(){
console.log("Analog Clock:", this.displayTime)
}

update(timer: Timer): void {
this.setDisplayTime(timer.time)
this.show()
}

unsubscribe(){
this.timer.unsubscribe(this)
}
}


const timer = new Timer()

new DigitalClock(timer)
new AnalogClock(timer)

timer.tick()
timer.tick()
timer.tick()