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.
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.
Lets dive into Observer Pattern now.
Normal RedDress class will look like this-
To become observable RedDress need to implement functionalities of Observable (point 1 below).
Now how will Observer look like?
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).
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 etc.
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.
- 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.
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
Normal RedDress class will look like this-
To become observable RedDress need to implement functionalities of Observable (point 1 below).
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 case buyDress() is called. (Point 2 below)
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.
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 etc.
- In such a case either the state of Observable is passed as parameter to the update method. update(int price);
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.
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.
Nice explanation indeed. Thanks.
ReplyDeleteThanks for this nice Explanation.
ReplyDeleteYour software should always be loosely coupled and highly Cohessed.