Introduction

Observer Pattern is one of the behavioral design pattern. Observer design pattern is useful when you are interested in the state of an object and want to get notified whenever there is any change. The object that watch on the state of another object are called Observer and the object that is being watched is called Subject. The Observer Pattern defines a one to many dependency between objects so that one object changes state, all of its dependents are notified and updated automatically. One to many dependency is between Subject(One) and Observer(Many). Observers themselves don’t have access to data, they are dependent on Subject to provide them data.

 

Intent

  • Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
  • Encapsulate the core (or common or engine) components in a Subject abstraction, and the variable (or optional or user interface) components in an Observer hierarchy.

 

Implementation

Observable (Subject) is interface or abstract class defining the operations for attaching and de-attaching observers to the client. ConcreteObservable maintain the state of the object and when a change in the state occurs it notifies the attached Observers. Observer interface define the operations to be used to notify this object.

 

Example

public interface Subject {

  // Methods to register and unregister observers
  public void register(Observer obj);
  public void unregister(Observer obj);
  
  // Method to notify observers of change
  public void notifyObservers();
  
  //method to get updates from subject
  public Object getUpdate(Observer obj);
}

public interface Observer {
  
  // Method to update the observer, used by subject
  public void update();
}

public class MyTopic implements Subject {

  private List<Observer> observers;
  private String message;
  
  public MyTopic(){
    this.observers=new ArrayList<>();
  }
  
  @Override
  public void register(Observer obj) {
    observers.add(obj);
  }

  @Override
  public void unregister(Observer obj) {
    observers.remove(obj);
  }

  @Override
  public void notifyObservers() {
    for (Observer obj : observers) {
      obj.update();
    }
  }

  @Override
  public Object getUpdate(Observer obj) {
    return this.message;
  }
  
  // Method to post message to the topic
  public void postMessage(String msg){
    this.message=msg;
    notifyObservers();
  }
}

public class MyTopicSubscriber implements Observer {
  
  private String name;

  public MyTopicSubscriber(String nm){
    this.name=nm;
  }
  
  @Override
  public void update() {
    String msg = (String) topic.getUpdate(this);
    System.out.println("Consuming message::" + msg);
  }
}

public class ObserverPatternTest {

  public static void main(String[] args) {

    // Create subject
    MyTopic topic = new MyTopic();
    
    // Create observers
    Observer obj1 = new MyTopicSubscriber("Obj1");
    Observer obj2 = new MyTopicSubscriber("Obj2");
    
    // Register observers to the subject
    topic.register(obj1);
    topic.register(obj2);	
    
    // Send message to subject
    topic.postMessage("New Message");
  }
}