Search⌘ K
AI Features

Observer Pattern

Explore the Observer pattern by building a simple Producer and Listeners. Understand how this design decouples event notifications and enhances asynchronous programming with RxJS. Gain insight into the core reactive concept that supports observable behavior.

We'll cover the following...

For a software developer, it’s hard to hear about Observables and not think of the venerable Observer pattern. In it, we have an object called Producer that keeps an internal list of Listeners subscribed to it. Listeners are notified, by calling their update method, whenever the state of the Producer changes. In most explanations of the Observer pattern, this entity is called Subject, but to avoid confusion with RxJS’s own Subject type, we call it Producer.

It’s easy to implement a rudimentary version of the pattern in a few lines:

Let’s see the code:

Javascript (babel-node)
function Producer()
{
this.listeners = [];
}
Producer.prototype.add = function(listener)
{
this.listeners.push(listener);
};
Producer.prototype.remove =
function(listener)
{
var index = this.listeners.indexOf(listener);
this.listeners.splice(index, 1);
};
Producer.prototype.notify =
function(message)
{
this.listeners.forEach(function(listener)
{
listener.update(message);
});
};

The Producer object keeps a dynamic list of Listeners in the instance’s listeners array, which will be updated whenever the Producer calls its notify method. In the following code, we create two objects that listen to notifier, an instance of Producer:

Javascript (babel-node)
// Any object with an 'update' method would work.
var listener1 = {update: function(message)
{
console.log('Listener 1 received:', message); }
};
var listener2 = {update: function(message)
{
console.log('Listener 2 received:', message); }
};
var notifier = new Producer();
notifier.add(listener1);
notifier.add(listener2);
notifier.notify('Hello there!');

Run the following program:

Javascript (babel-node)
class Producer {
constructor() {
this.listeners = [];
}
add(listener) {
this.listeners.push(listener);
}
remove(listener) {
const index = this.listeners.indexOf(listener);
this.listeners.splice(index, 1);
}
notify(message) {
this.listeners.forEach(listener => {
listener.update(message);
});
}
}
// Any object with an 'update' method would work.
const listener1 = {
update: message => {
console.log("Listener 1 received:", message);
}
};
const listener2 = {
update: message => {
console.log("Listener 2 received:", message);
}
};
const notifier = new Producer();
notifier.add(listener1);
notifier.add(listener2);
notifier.notify("Hello there!");

Both listener1 and listener2 are notified whenever the Producer notifier updates its internal state, without us having to check for it.

Our implementation is simple, but it illustrates how the Observer pattern allows decoupling between the events and the listener objects that react to them.