Observer Design Pattern

16 / Aug / 2016 by Ajay Kumar 2 comments

Observer Design Pattern

When we build applications using object oriented paradigm, we try to develop each of our component independent of all other component that exist in our system. Although component independency fixes a lot of problem and it’s very convenient, but sometime it makes difficult to establish interaction between these independent component. So the problem is how we can make each of these component interact with each other.

The Observer Pattern helps us solve this problem because each class or component in our existing system can be notified about the state change of other component.The Observer Pattern is a kind of behavior pattern which is concerned with the assignment of responsibilities between objects.

The Observer Pattern defines a one-to-many dependency between objects so that when one object changes its state, all its dependents  are notified and updated automatically. The Observer pattern describes these dependencies. The key objects in this pattern are subject and observer. A subject may have any number of dependent observers. All observers are notified whenever the subject undergoes a change in its state. In response, each observer will query the subject to synchronize its state with the subject state.

A better way to understand this pattern is through example.

Let’s assume that we are working for a fantastic e-commerce site that has almost all kind of products and provide the latest information of the trends, new coupons, discount and other offers to its subscribed user. A user can subscribe to his/her favorite product (which may be currently out of stock) and get notification once the product is available in stock or the product is available at discount or when its price decreases.

For easy understanding let’s see how to develop one of the above feature using observer design pattern.

Requirement

While visiting our ecommerce site, a customer found one product very interesting and he has a great desire to buy that product.Unfortunately that product is currently out of stock. To avoid the customer disappointment, there is an option available for the customer to get subscribed to that product. So once the product is available in stock, subscribed user can be notified for its availability.

So here user is an observer who wants to observe the Product for its availability. In other words whenever the state of subject i.e product changes from ‘out of stock’ to ‘in stock’, the observer (user) should be notified.

Here product(subject) and user(observer) are two separate component and want to interact with each other.

Implementation

There are four participants in the Observer pattern:

  • Subject, which is used to register observers. Objects use this interface to register as observers and also to remove themselves  from being observers.
  • Observer, defines an updating interface for objects that should be notified of changes in a subject. All observers need to  implement the Observer interface. This interface has a method update(), which gets called when the Subject’s state changes.
  • ConcreteSubject, stores the state of interest to ConcreteObserver objects. It sends a notification to its observers when its state  changes. A concrete subject always implements the Subject interface. The notifyObservers() method is used to update  all the current observers whenever the state changes.
  • ConcreteObserver, maintains a reference to a ConcreteSubject object and implements the Observer interface. Each observer  registers with a concrete subject to receive updates.  

Although we can define all the above mentioned participants our self but Java brings a lot to the table. There are already methods, classes and interfaces defined in java.util package meant for easy implementation of this pattern. We can use these components of java.util package and customise it as per our requirement.

Following component are used from java.util package to implement this pattern:-

  1. public interface Observer- All observer needs to implement this interface to get notification about the state change of subject.
    Note- In our case User is an observer so user class needs to implement this interface.
    This interface has one method- void update(Observable o, Object arg): This method is called whenever the observed object is changed. An application calls an Observable object’s notifyObservers() method to have all the object’s observers notified of the change.
  2. public class Observable- It is basically a subject to whom observer wants to observe. So it can be sub-classed to represent an object that the application wants to have observed.
    Note- In our case Product is a subject that needs to be observed. So Product class needs to be the sub-class of Observable class.

Observable class has below useful methods-

  1. public synchronized void addObserver(Observer o)- Adds an observer to the set of observers for this object, provided that it is not the same as some observer already in the set.
    Note- The order in which notifications will be delivered to multiple observers is not specified.
  2. public synchronized void deleteObserver(Observer o)- Deletes an observer from the set of observers of this object.
  3. public synchronized void deleteObservers()- Clears the observer list so that this object no longer has any observers.
  4. public void notifyObservers()
  5. public void notifyObservers(Object arg) – If this object has changed, as indicated by the hasChanged() method, then notify all of its observers and then call the clearChanged() method to indicate that this object has no longer changed.
    Note- Each observer has its update() method called with two arguments.
  6. protected synchronized void setChanged()- Marks this Observable object as having been changed; the hasChanged() method will now return true.
  7. protected synchronized void clearChanged()- Indicates that this object has no longer changed, or that it has already notified all of its observers of its most recent change.
  8. public synchronized boolean hasChanged()- Tests if this object has changed.
  9. public synchronized int countObservers()- Returns the number of observers of this Observable object.

Sample Code of our use case

Step 1:- Define Subject

For simplicity and better understanding we will be using ‘Observable’ interface as Subject, provided in java.util package meant for implementing observer design pattern.  

Step 2:- Define Observer

We will be using ‘Observer’ interface as provided in java.util package.

Step 3:- Define  ConcreteSubject

[js]package com.intelligrape;
import java.util.Observable;
import java.util.Observer;
public class Product extends Observable {
String productId;
String productName;
Integer stockQuantity;
public Product(String productId, String productName, Integer stockQuantity) {
super();
this.productId = productId;
this.productName = productName;
this.stockQuantity = stockQuantity;
}
// Getters and Setters of the field…
public void setStockQuantity(Integer stockQuantity) {
this.stockQuantity = stockQuantity;
System.out.println("Setting stock quantity of " + this.toString());
if (this.stockQuantity > 0) {
// Whenever stock quantity of current product is set to
// greater than zero, notify the subscribed user
this.setChanged();
this.notifyObservers();
}
}
@Override
public String toString() {
return "Product [productId=" +productId + ", productName=" + productName
}
@Override
public synchronized void addObserver(Observer o) {
System.out.println("Subscribing " + o.toString() + " for notification of " + this.toString());
super.addObserver(o);
}
@Override
public synchronized void deleteObserver(Observer o) {
System.out.println("Un-subscribing "+ o.toString() + " from notification of " +
this.toString());
super.deleteObserver(o);
}
@Override
public void notifyObservers() {
System.out.println("Notifying observers for availability of " + this.toString());
super.notifyObservers();
// if it requires to notify observer only for one time, then delete
// all the observers after notification by un-commenting below line.
// this.deleteObservers();
}
}[/js]

Step 4:- Define  ConcreteObserver

[js]package com.intelligrape;
import java.util.Observable;
import java.util.Observer;
public class User implements Observer {
String id;
String name;
public User(String id, String name) {
super();
this.id = id;
this.name = name;
}
// Getters and Setters…
@Override
public String toString() {
return "User [id=" + id + ",name=" + name + "]";
}
@Override
public void update(Observable o, Object arg) {
System.out.println(this.toString() + " is notified successfully about the availability of " + o.toString());
}
}[/js]

Define Main class

 

[js]package com.intelligrape;
public class Test {
public static void main(String[] args) {
Product product1 = new Product("P1","Jacket", 0);
Product product2 = new Product("P2","Jeans", 5);
User person1 = new User("customer 1","Ajay");
User person2 = new User("customer 2","Saktiman");
User person3 = new User("customer 3","Rajnikant");
// Adding observer for product1
product1.addObserver(person1);
product1.addObserver(person2);
// Setting stock quantity of product1 will notify all observer of product1
product1.setStockQuantity(8);
// Adding observer for product2
product2.addObserver(person1);
product2.addObserver(person2);
product2.addObserver(person3);
product2.setStockQuantity(0);
// Setting stock quantity of product2 will notify all observer of product2
product2.setStockQuantity(10);
// Removing person1 from observer list of product2
// Now person1 will not get notification about product2
product2.deleteObserver(person1);
product2.setStockQuantity(15);
}
}[/js]

Scope Of Further Improvement In Sample Code

Instead of passing the entire subject, it is good to define a separate type and pass it as parameter to the handler method in the observer class. This type basically contains the meta information about the event. Eg source of event, time at which event was generated, what are the actual property of subject that leads to change in state of Subject etc. In our case subject domain is very small So we are not creating any separate type.

Other Use Cases:-

  1. Consider an e-commerce business. This pattern can be used in following scenario:-
    1. An admin user can be notified with the increase in demand of given product. Whenever the number of subscribed user for a given product increases more than a given threshold then the admin user can be notified for the increase in demand for that product and that product can be marked as highly demanded product.
    2. Similarly whenever the quantity of highly demanded product falls below a given threshold then the admin user can be notified for that product.
    3. An admin user can associate a discount/coupon with multiple product. So any change in discount/coupon (eg change in discount percentage/value or associating/disassociating product to/from coupon) must be notified to its associated product. So that the associated product can be updated with new available discount/coupon.
  2. Consider an excel sheet, data is shown to the user in different views. Generally data is shown in grid cells and as required different graphs, charts can be created for same data. Underlying data is same and when that data (subject) state changes all the different view (observer) are updated.
  3. The observer pattern is used in the model view controller (MVC) architectural pattern. In MVC this pattern is used to decouple the model from the view. View represents the Observer and the model is the Observable object.
    Example- Popular JSF technology also uses observer design pattern along with other design design pattern. The JSF framework implements the Observer pattern in UI components. JSF technology has two kinds of built-in events: ActionEvent and ValueChangedEvent. ActionEvent is useful in determining the activation of user interface components such as buttons. When a user clicks on the button, the JSF implementation notifies one or more action listeners added to the button. The button is activated or the state of the button (subject) changes. All listeners (or observers) are notified of the changes of state in subject that are added to the button. Similarly, when the value in the input UI component changes, the JSF implementation notifies ValueChangeListeners.
  4. A company can have many shareholders. So any change in policy of company needs to be notified to its shareholders.
  5. A news agency gather news and publish them to different subscribers.  So when an event occurs, all the subscribers get notified. The solution need to be extensively enough to support new types of subscribers(maybe new communication technologies will appear).
FOUND THIS USEFUL? SHARE IT

comments (2)

Leave a Reply

Your email address will not be published. Required fields are marked *