Used to notuify and update objects (observers) when the value of a specific object (observable) changes

Basically, the Observer Pattern works beautifully when you have 2 things :

  1. One / more objects (observable) whose state you wish to monitor
  2. One / more objects (observers) whose state you wish to change when the observable undergoes a state change

The Observer Pattern is widely implemented in all places where state management is imperative like :

  1. Redux, for rolling UI changes on store updates Β 
  2. Microsoft Excel, where, when you change the value of a cell, the column and say maybe a graph based off the column get updated

Resources

The source code for all prominent design patterns has been properly implemented and documented in this GitHub repostitory by me.β€Œ

crew-guy/Design-Patterns
A collection of the design patterns, implemented in java, as originally created by the GoF - crew-guy/Design-Patterns

Project Description

Here, in this article, we will be building a simple application that mimics Microsoft Excel's simple functionality where if you change a value in a cell, the column and the graph dependent on this cell's value get immediately re-rendered/ updated !!πŸ”₯β€Œ

Also, here, we will be working with something known as the Push style in the Observer Pattern so here, the Observers will be idle so it is the Observable that will push the value to notify them to re-render themselves

Implementing the Observer interface

It is an interface which lays out the skeleton of the methods each of the observers should have

It helps maintain the Open-Closed Principle, something is fundamental to good Object Oriented Programming programs. It states that the "software entities must be open to extension, but closed for modification"
Thus, we can scale no. of observers, easily without ever changing existing code.

It lays out the prototype of the update( ) method i.e. what the observers (child classes implementing this interface) do when the observable changes

public interface Observer {
    void update(int value);
}
Child classes implementing the Observer interface. These are what bring about changes when the observable(s) change(s)

They polymorph the method (viz the update() method) specified by the interface. To understand about working with polymorphism in detail be sure to check out this blog, I wrote sometime back

Template Pattern | Java
One object many forms ! Here, we up our strategy game up by working with templates, inheritance and polymorphism

In our case, this happens - when a cell (observable) value changes :
1. Chart (observer) => Get's re-rendered
2. Column (observer) => Get's recomputed

public class Chart implements Observer{
    @Override
    public void update(int value) {
        System.out.println("Chart was just updated with value :" + value);
    }
}
Chart.java
public class Spreadsheet implements Observer{
    @Override
    public void update(int value) {
        System.out.println("Spreadsheet was just updated with value :" + value);
    }
}
Spreadsheet.java

Implementing the Subject

It is a simple abstract parent class having the collection of observers and implementations of 3 methods on them

Method Name Function Example
addObserver Adds a new observer to the list/collection Adding a new column in Google Sheets which subscribes to an existing cell
removeObserver Removes an observer from the collection Removing a YouTube subscriber or a facebook follower
notifyObserver Notifies all observers (by iteration over each one ) that value of observable has changed Slack notification to all members in a channel listening onto the successful merge of their code to a GitHub repository

Here, all the subject does is exactly this only :

public class Subject {
    public List<Observer> observers = new ArrayList<>();

    public void addObserver(Observer observer){
        observers.add(observer);
    }

    public void removeObserver(Observer observer){
        observers.remove(observer);
    }

    public void notifyObservers(int value){
        for(var observer : observers){
            observer.update(value);
        }
    }
}
Subject.java

Implementing the ConcreteSubjects

These are observables extending the Subject class. They hold values that can be subscribed to by observers

These implement 2 methods


Method Function
getVal() In case the observers wish to use the updated value for something
setVal() To set the value, thereby triggering a change among all observers

Here, we will simply have 1 observable called DataSource which contains the value the observers are watching

public class DataSource extends Subject {
    private Integer value;

    public Integer getValue() {
        return value;
    }

    public void setValue(Integer value) {
        this.value = value;
        notifyObservers(value);
    }
}
DataSource.java

Using this pattern in our application

Import all the necessary classes and modules into main.java for a final showdown of our application ! Here, I'll be simply adding 2 sheets and 1 chart as observer to our data and re-render/ Β all observers when I set the value in the Β 

var dataSrc = new DataSource();
var sheet1 = new Spreadsheet();
var sheet2 = new Spreadsheet();
var chart = new Chart();

dataSrc.addObserver(sheet1);
dataSrc.addObserver(sheet2);
dataSrc.addObserver(chart);

dataSrc.setValue(1);
Main.java

Conclusion

Congrats on unlocked the secret of how most modern implementations of state management work under the hood. You should feel pretty comfortable now developing the dynamic state functionalities in your applications. Until next time...β€Œ

eye

References..

Whatever I have learnt and implemented here in code as well as the explanation is all from the teachings of the brilliant Mosh Hamedani and his course on Design Patterns which I would recommend you to take if you are really interested in exploring the beauty of Object Oriented Programming

The Ultimate Design Pattern Series
Ace your coding job interview. Learn to write maintainable and extensible code.