The Observer Pattern in Java
Get an overview of the Java observer pattern using an inventory example.
Lizza decides to get a new dress for her 18th birthday party. She goes online to her favourite website fashionworld.com and selects a perfect Red dress. But oops its out of stock.
|THE RED DRESS|
She tries to find another dress but there is nothing that can replace it. So, she goes back to the dress, registers her email id and click on "Notify Me" button.
You must be wondering why am I telling you story of Red Dress? Reason is "Notify Me" button is an example of Observer Pattern.
Here is how "Notify Me" button works? As soon as the dress will be in stock she will be notified via an email.
Similarly, there could be other users waiting for the Red Dress. As shown below user1, user2 and user3 have registered for notification just like Lizza. So, they will be notified once dress is available.
User4 is not interested in Red Dress so, she never registered by clicking "Notify Me" button. No email will be sent to her when the dress is 'In Stock'
If user1 finds another dress and is no longer interested in the Red Dress. Then user1 can get the registration removed. In this case she will no longer be informed when dress is available.
Lets dive into Observer Pattern now.
- All the users who registered for notification in the above case are Observers (user1, user2, user3).
- The subject of their observation is Red Dress. So, Red Dress is Observable.
There is one Red dress but many users interested in it.
Observer Pattern defines one to many relationship between Observable and observers
When the state of dress changes from 'Out of stock' to 'in stock' all users are notified.
When Observable changes state all Observers are notified
User4 is not registered hence he is not an observer in this case.
If User1 gets her registration removed later. She will not remain an Observer in that case and will not be notified.
Observers subscribe for an Observable. Observers can unsubscribe at any time
Time to write Java code to implement this pattern-
What functionalities will be required in an Observable?
- Register observer
- Remove observer
- Notify observer on state change
RedDress maintains a list of all registered users or Observers (point 2 below)
A new user is added to the users list from addObserver() method (point 3 below)
user is removed from the list from removeObserver() method is called (point 4 below)
At any point of time RedDress will have the list of all the users who need to be notified.
'Observable maintains a list of Observers'
notifyObserver() method has responsibility of informing all the observers about the change.(point 5 below)
Any change to inStock will happen from the setter setInStock(). Whenever, this happens all the users need to be notified simply by calling notifyObserver method (point 6 below)
Now how will Observer look like?
Observable need to update all the Observers. So, Observer should have a method update() which Observable can call to notify about the change.
So, notifyObserver() method of Observable will call update() method of all Observers.
If a user has to become an Observer it will implement Observer functionality (Point 1 below).
From update method User can do something when state of Observable is changed. In this casebuyDress() is called. (Point 2 below)
Here, User is not doing much with the status of Observable. But in some cases user might need to know the changed current status. e.g. if user need to know the change in price of the dress. In such a case the state of Observable is passed as parameter to the update method.
Once, user calls buyDress() he is not interested in any status change of RedDress. So, it calls unsubscribe() to get removed from the observer list of RedDress (Point 3 below).
For this removeObserver of Observable need to be called. User keeps a reference of Observable so that it can call removeObserver when required.
What we achieved?
We were able to separate the logic of Observer and Observable and make them independent of each other. Now user can has its own independent functionality e.g. goToWork(), driveCar() or any other functionality.
And any change to that will not impact our Observable. Vice versa is also true any change to Observable will not impact Observer.
Due to use of Interfaces, Observable and Observers are loosely coupled.
In future if we decide that User should not implement Observer Interface no code change is required in Observable class as it uses Observer Interface and not the concrete class.
Similarly any new class can become an Observer by simply implementing Interface and it will not impact Observable.