DEV Community

eidher
eidher

Posted on • Edited on

Observer Pattern

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
Alt Text

Participants

  • Subject: knows its observers. Any number of Observer objects may observe a subject. Provides an interface for attaching and detaching Observer objects.
  • ConcreteSubject: stores state of interest to ConcreteObserver. Sends a notification to its observers when its state changes
  • Observer: defines an updating interface for objects that should be notified of changes in a subject.
  • ConcreteObserver: maintains a reference to a ConcreteSubject object. Stores state that should stay consistent with the subject's. Implements the Observer updating interface to keep its state consistent with the subject's.

Code

public class Main {

    public static void main(String[] args) {
        ConcreteSubject s = new ConcreteSubject();
        s.attach(new ConcreteObserver(s, "X"));
        s.attach(new ConcreteObserver(s, "Y"));
        s.attach(new ConcreteObserver(s, "Z"));
        s.setSubjectState("ABC");
        s.notifyObservers();
    }
}

public class Subject {

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

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

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

    public void notifyObservers() {
        for (Observer o : observers) {
            o.update();
        }
    }
}

public class ConcreteSubject extends Subject {

    private String subjectState;

    public String getSubjectState() {
        return subjectState;
    }

    public void setSubjectState(String subjectState) {
        this.subjectState = subjectState;
    }    
}

public interface Observer {

    void update();
}

public class ConcreteObserver implements Observer {

    private String name;
    private ConcreteSubject subject;

    public ConcreteObserver(ConcreteSubject subject, String name) {
        this.subject = subject;
        this.name = name;
    }

    @Override
    public void update() {
        String observerState = subject.getSubjectState();
        System.out.println("Observer " + name + " state is " + observerState);
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

Observer X state is ABC
Observer Y state is ABC
Observer Z state is ABC
Enter fullscreen mode Exit fullscreen mode

Java Builtin Observer

public class Main {

    public static void main(String[] args) {
        ConcreteSubject s = new ConcreteSubject();
        s.addObserver(new ConcreteObserver(s, "X"));
        s.addObserver(new ConcreteObserver(s, "Y"));
        s.addObserver(new ConcreteObserver(s, "Z"));
        s.setSubjectState("ABC");
        s.notifyObservers();
    }
}

import java.util.Observable;

public class ConcreteSubject extends Observable {

    private String subjectState;

    public String getSubjectState() {
        return subjectState;
    }

    public void setSubjectState(String subjectState) {
        this.subjectState = subjectState;
        setChanged();
    }

}

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

public class ConcreteObserver implements Observer {

    Observable subject;
    private String name;

    public ConcreteObserver(Observable subject, String name) {
        this.subject = subject;
        this.name = name;
    }

    @Override
    public void update(Observable obs, Object arg) {
        if(obs instanceof ConcreteSubject) {
            ConcreteSubject observable = (ConcreteSubject)obs;
            System.out.println("Observer " + name + " state is " + observable.getSubjectState());
        }       
    }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)