tl  tr
  Home | Tutorials | Articles | Videos | Products | Tools | Search
Interviews | Open Source | Tag Cloud | Follow Us | Bookmark | Contact   
 Design Patterns > Java Design Patterns > Observer

Observer 

Observer pattern comes under Behavioral design pattern. It defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Behaviour & Advantages

  • Useful in complex event processing systems.
  • It decouples subject and observers so that both can be enhanced independently.
  • Dynamic relations can be built between subject and observer at runtime.
Participants
  • Subject
    Provides an interface for attaching or detaching Observers.
  • Concrete Subject
    Object which needs to be monitored by Observers for state change.
  • Observer
    Defines an abstract interface for updating subjects state change.
  • Concrete Observer
    An implementation of Observer which gets notified upon subjects state change.

This example shows a simple bidding system where a list of organizations compete for a project. The system accepts the bid with highest amount.

Java provides two classes supporting Observer pattern. Class java.util.Observable acts as Subject and Project class as Concrete Subject. Each organization can submit a bid against the project. Interface java.util.Observer acts as Observer and Bid as Concrete Observer. When a bid submitted by particular organization is accepted, all other other organizations gets notified. The Project class is shown below,

File Name  :  
com/bethecoder/tutorials/dp/observer/Project.java 
   
package com.bethecoder.tutorials.dp.observer;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;

public class Project extends Observable {

  private String projectName = null;
  private List<Bid> submittedBids = new ArrayList<Bid>();
  private Bid acceptedBid = null;
  
  public Project(String projectName) {
    this.projectName = projectName;
  }
  
  public void submitBid(Bid bid) {
    submittedBids.add(bid);
    this.addObserver(bid);
  }
  
  /**
   * Accept the max bid.
   */
  public void acceptBid() {
    
    int max = 0;
    Bid maxBid = null;
    
    for (int i = ; i < submittedBids.size() ; i ++) {
      if (max < submittedBids.get(i).getAmount()) {
        max = submittedBids.get(i).getAmount();
        maxBid = submittedBids.get(i);
      }
    }
    
    if (maxBid != null) {
      this.acceptedBid = maxBid;
      this.setChanged();
      this.notifyObservers(this.acceptedBid);
    }
  }
  
  public List<Bid> getSubmittedBids() {
    return submittedBids;
  }
  
  public void setSubmittedBids(List<Bid> submittedBids) {
    this.submittedBids = submittedBids;
  }
  
  public Bid getAcceptedBid() {
    return acceptedBid;
  }
  
  public void setAcceptedBid(Bid acceptedBid) {
    this.acceptedBid = acceptedBid;
  }

  public String getProjectName() {
    return projectName;
  }

  public void setProjectName(String projectName) {
    this.projectName = projectName;
  }
}
   

The Bid class is shown below,

File Name  :  
com/bethecoder/tutorials/dp/observer/Bid.java 
   
package com.bethecoder.tutorials.dp.observer;

import java.util.Observable;
import java.util.Observer;

public class Bid implements Observer {

  private String bidderName;
  private int amount;
  
  public Bid(String bidderName, int amount) {
    super();
    this.bidderName = bidderName;
    this.amount = amount;
  }

  @Override
  public void update(Observable paramObservable, Object paramObject) {
    Project project = (ProjectparamObservable;
    Bid acceptedBid = (BidparamObject;
    System.out.println("Mail box [" + bidderName + "] : '" 
        acceptedBid.getBidderName() "' won '" + project.getProjectName() "' project.");
  }

  public String getBidderName() {
    return bidderName;
  }

  public void setBidderName(String bidderName) {
    this.bidderName = bidderName;
  }

  public int getAmount() {
    return amount;
  }

  public void setAmount(int amount) {
    this.amount = amount;
  }
}
   

Observer usage is shown below,

File Name  :  
com/bethecoder/tutorials/dp/observer/Test.java 
   
package com.bethecoder.tutorials.dp.observer;

public class Test {

  /**
   @param args
   */
  public static void main(String[] args) {
    Project project = new Project("Adhaar");
    Bid infyBid = new Bid("Infosys"120000);
    Bid tcsBid = new Bid("TCS"90000);
    Bid ibmBid = new Bid("IBM"80000);
    Bid midTreeBid = new Bid("MindTree"180000);
    
    project.submitBid(infyBid);
    project.submitBid(tcsBid);
    project.submitBid(ibmBid);
    project.submitBid(midTreeBid);
    
    /**
     * Accept max of above bids.
     */
    project.acceptBid();
    
  }

}
   

It gives the following output,
Mail box [MindTree] : 'MindTree' won 'Adhaar' project.
Mail box [IBM] : 'MindTree' won 'Adhaar' project.
Mail box [TCS] : 'MindTree' won 'Adhaar' project.
Mail box [Infosys] : 'MindTree' won 'Adhaar' project.



 
  


  
bl  br