Observer Design Pattern in Java

In this article we will look int the Observer design pattern which come under behavioral design pattern and try to understand what problems it solves and its applicability.

Observer Design Pattern in Java
Observer Design Pattern in Java

Introduction

Observer is a behavioral design pattern. In this design pattern an observable is an object which notifies observers about the changes in its state.

Let’s understand observer pattern in details

Observer pattern is used to create a one-to-many dependency between objects so that when one object (the subject) changes its state, all its dependents (observers) are notified and updated automatically.

In this there are many observers (i.e., subscriber/consumer) that are observing a particular subject (i.e., publisher/producer). Observers register themselves to a subject to get a notification when there is a change made inside that subject. To make it some sort of loose coupled, observer object allows to register or unregistered from topic any time.

Observer design pattern components

Subject: The subject maintains a list of observers and notifies them of state changes.
Observer: The observer interface defines the contract for concrete observer classes.
Subscribers: All other object that are interested in the state/changes to the publisher’s state.
Publisher: Object that notify other object about the change in the state of subject.
ConcreteSubject: A class that implements the subject interface and manages the observers.
ConcreteObserver: A class that implements the observer interface and receives notifications.

Observer design Pattern Example

Step 1: Observer Interface: an interface to provide basic methods for implementing Observer classes.

public interface Oberver {
   void update(Message message);
}

Step 2 : Message: lets create a message class to , to represent the message content

package com.javaocean.designpattern.observer;

public class Message {
  final String messageContent;

  public Message(String msg) {
   this.messageContent = msg;
  }

  public String getMessageContent() {
   return messageContent;
 }
}

Step 3: Lets create the subject interfac e, subject provide abstract method to maintains a list of observers and notifies them of state changes.

public interface Subject { 
   void subscribe(Oberver oberver);
   void unSubscribe(Oberver oberver);
   void notifyUpdate(Message message);
 }

step 4: ConcreteSubject: A class that implements the subject interface and manages the observers.

package com.javaocean.designpattern.observer;

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

public class MessagePublisher implements Subject {

    private List<Oberver> observers = new ArrayList<>();

    @Override
    public void subscribe(Oberver oberver) {
       observers.add(oberver);
    }

    @Override
    public void unSubscribe(Oberver oberver) {
       observers.remove(oberver);
    }

    @Override
    public void notifyUpdate(Message message) {
       for (Oberver oberver : observers) {
       oberver.update(message);
    }
  }
}

Steps 5: Lets create couple of MessageObserver that will implement Observer interface

Message observer 1

package com.javaocean.designpattern.observer;

public class MessageObserver1 implements Oberver {
   @Override
   public void update(Message message) {
   System.out.println("MessageObserver 1 : " + message.getMessageContent());
  }
}

Message observer 2

package com.javaocean.designpattern.observer;

public class MessageObserver2 implements Oberver {
   @Override
   public void update(Message message) {
   System.out.println("MessageObserver 2 : " + message.getMessageContent());
  }
}

Message Observer 3

package com.javaocean.designpattern.observer;

public class MessageObserver3 implements Oberver {
  @Override
  public void update(Message message) {
  System.out.println("MessageObserver 3 : " + message.getMessageContent());
 }
}

 

Message Observer 4

package com.javaocean.designpattern.observer;

public class MessageObserver4 implements Oberver {
  @Override
  public void update(Message message) {
  System.out.println("MessageObserver 4 : " + message.getMessageContent());
 }
}

Message Observer 5

package com.javaocean.designpattern.observer;

public class MessageObserver5 implements Oberver {
    @Override
    public void update(Message message) {
    System.out.println("MessageObserver 5 : " + message.getMessageContent());
  }
}

 

Step 5 Test : Lets create simple program to Test Observer

package com.javaocean.designpattern.observer;

public class TestObserver {
  public static void main(String[] args) {

  MessagePublisher publisher = new MessagePublisher();

  MessageObserver1 messageObserver1 = new MessageObserver1();
  MessageObserver2 messageObserver2 = new MessageObserver2();
  MessageObserver3 messageObserver3 = new MessageObserver3();
  MessageObserver4 messageObserver4 = new MessageObserver4();
  MessageObserver4 messageObserver5 = new MessageObserver5();
 
  Message message = new Message("Observer");

  publisher.subscribe(messageObserver1);
  publisher.subscribe(messageObserver2);
  publisher.subscribe(messageObserver3);
  publisher.subscribe(messageObserver4);

  publisher.notifyUpdate(new Message("Hello Observer"));

  publisher.subscribe(messageObserver5); // Subscribe 
  publisher.unSubscribe(messageObserver2); // unSuscribe
  publisher.unSubscribe(messageObserver1); // unSuscribe
  publisher.notifyUpdate(new Message("My State Updated !!"));

 }
}

Output: Run the above program will give following result

MessageObserver 1 : Hello Observer
MessageObserver 2 : Hello Observer
MessageObserver 3 : Hello Observer
MessageObserver 4 : Hello Observer
MessageObserver 3 : My State Updated !!
MessageObserver 4 : My State Updated !!
MessageObserver 5 : My State Updated !!

You may find other post on different topic that might be helpful, Please have a look

  1. Factory design pattern in Java
  2. Builder design pattern
  3. Abstract class and Interface
  4. Optional in Java
  5. What is exception handling in java

2 thoughts on “Observer Design Pattern in Java”

Leave a Comment