Design patterns are really important to us as programmers because they tell us how to organize our code a certain way so it becomes more scalable on the long run and there's a variety of them, each with its own advantages and pitfalls. In this post however, we will have a little introduction to the Observer Design Pattern, we will talk about what it is and how to implement it in a real project with JavaScript.
What is the Observer Pattern?
The Observer Pattern is a part of a larger category known as "Behavioural Design Patterns", that define different ways in which objects can communicate with each other.
In the observer pattern we define an object commonly known as the subject, this object has a list of observers (also known as subscribers), so that everytime the state of the subject changes, it notifies its subscribers and they can react accordingly.
How To Implement It?
In order to use this pattern, we must create the following classes:
-
Observer: It's an abstract class that represents the observer or subscriber. It only has one method named
update
, with the following signature:
The update
method receives one argument named model
, which is an instance of the Subject
class that contains the updated state. The logic that goes inside this method depends on the class that inherit it.
- Subject: It's an abstract class that represents the object whose state is going to change constantly. It is defined as follows:
The observers
field is an array of objects that subscribed to the subject, these objects will be notified when the state of the subject instance change. Regarding the other three functions, the good news is that the logic of these will (most likely) never change, because of the nature of the design pattern itself.
The subscribe
function receives an observer instance and include it in the array. In JavaScript, we would define it as follows:
function subscribe(observer) {
this.observers.push(observer);
}
The unsubscribe
function does exactly what you think it does, it removes the observer instance from the array. We could just call the splice
function, but there is a problem, we don't know in advance how two observers can be equal (because it depends on the class that inherits from the Observer class), so we need to provide a function to evaluate whether two observers are the same. With that in mind, in JavaScript we would do something like this:
function unsubscribe(observer, areEqual) {
if (typeof areEqual === "function") {
this.observers = this.observers.filter(o => !areEqual(o, observer));
} else {
throw new Error("A function is required");
}
}
Lastly, the notify
function cycles through the array, calls the update
method on every object and passes itself as the required argument, like this:
function notify() {
this.observers.forEach(o => o.update(this));
}
Our Code Example: A CryptoCurrency App
Now that we know the basics of the observer pattern, we are all set to apply them in a real project. In this case, we will develop a small cryptocurrency app that let users subscribe to a particular currency and notifies them when the price changes.
If you want to code along, go to the following GitHub repo here and download the starting code, it contains the two classes we discussed earlier.
In case you don't want to code but are interested in the topic, I recommend you to check the file structure of the project, so you can get familiar with it.
Inside the js
folder, let's create a new file called currency.js
, here we will create the class representation of our currency, like seen in the following diagram:
This class will inherit from the Subject class. The methods increment
and decrement
will change the state (price) of the currency and therefore notify the users that subscribed to it. The resulting class would look like this:
Looks good. Now we need to create the class representation of the user, let's keep it simple and just attach two attributes, a name and an email, what is important is that this class will inherit from the Observer class and re-define the update
method printing messages to the console, alerting about the change, like this:
Now let's get to the fun part! In the index.js
file let's create two new currencies and two new users (for starters, but you can create as much as you like!):
Now we have to subscribe the users to the currencies using the subscribe
method on the subject instance, like this:
Lastly, we need to make the currencies fluctuate randomly and repeatedly. Inside of a for
loop, let's use the setTimeOut
function to call the increment
and decrement
on the currencies with a random amount of time, like this:
Now if we start a local server we should see in the messages in the console, alerting the user about the changing price of the currency they subscribed to, something like this:
¡Awesome 🎉! It works as intended.
Let's Recap
In this article we learned:
- What is the Observer Design Pattern
- How to implement the pattern in our programs by learning what are the classes involved (Subject and Observer)
- How we could use this pattern in a real application using JavaScript
I hope you find this useful and I would love to read your comments and suggestions down below. Thank you for reading, until next time 👋.
Bonus
It can be a little hard to read the messages in the console because there's no way to tell if the alert is from one currency or another, that's why we can add a little style to the messages by creating a color
field in the CryptoCurrency
class, like this:
Then in the User
class, we can add CSS styles to the message logged in the update
method, like this:
Lastly in the index.js
file, we need to pass the color we desire to the CryptoCurrency
constructor, in my case those colors will be gold and purple:
Now if we run once again our application in the browser, we will see that the titles of the alerts are colored and it's much easier to read.
Top comments (0)