How to implement Observer Pattern in TypeScript

Observer Pattern is used when there is a publisher(which is observable), and there many observers. When there is a change in the publisher’s state, the publisher will notify its observers to update. The publisher can also add and remove observers.

In the following example, we will simulate a Weather Station. Assume that there is a WeatherData Object which store temperature data, and there are many Displays that display that temperature data, such as PhoneDisplay and ComputerDisplay. When there is a change in the temperature, the WeatherData will notify its displays to update .

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
interface IObserver {
  update(obs: IObservable);
}

interface Display {
  display();
}

interface IObservable {
  observers: Array<IObserver>;
  add(o: IObserver);
  remove(o: IObserver);
  notify();
}

class WeatherData implements IObservable {
  temperature: number;
  observers: Array<IObserver>;

  constructor(temperature: number) {
    this.temperature = temperature;
    this.observers = [];
  }
  add(o: IObserver) {
    this.observers.push(o);
  }
  remove(o: IObserver) {
    this.observers = this.observers.filter(item => item != o);
  }
  notify() {
    this.observers.forEach(o => o.update(this));
  }
  getTemperature() {
    return this.temperature;
  }
  temperatureChanged() {
    this.notify();
  }
  setTemperature(temperature: number) {
    this.temperature = temperature;
    this.temperatureChanged();
  }
}

class PhoneDisplay implements IObserver, Display {
  temperature: number;
  weatherData: WeatherData;
  constructor(weatherData: WeatherData) {
    this.weatherData = weatherData;
    weatherData.add(this);
    this.temperature = weatherData.getTemperature();
    this.display();
  }
  update(weatherData: WeatherData) {
    this.temperature = weatherData.getTemperature();
    this.display();
  }
  display() {
    console.log('Current Temperature From PhoneDisplay: ', this.temperature);
  }
}

class MonitorDisplay implements IObserver, Display {
  temperature: number;
  weatherData: WeatherData;
  constructor(weatherData: WeatherData) {
    this.weatherData = weatherData;
    weatherData.add(this);
    this.temperature = weatherData.getTemperature();
    this.display();
  }
  update(weatherData: WeatherData) {
    this.temperature = weatherData.getTemperature();
    this.display();
  }
  display() {
    console.log('Current Temperature From MonitorDisplay: ', this.temperature);
  }
}

const weatherData = new WeatherData(23);
const phoneDisp = new PhoneDisplay(weatherData);
const moniorDisp = new MonitorDisplay(weatherData);
weatherData.setTemperature(25);

Result

1
2
3
4
Current Temperature From PhoneDisplay:  23
Current Temperature From MonitorDisplay:  23
Current Temperature From PhoneDisplay:  25
Current Temperature From MonitorDisplay:  25