Java Understanding Observer Patterns

Keywords: Java JDK SpringBoot github

Foreword: Recently, in learning RxJava, RxJava has been extended on the basis of observer mode. This article takes you to understand the observer mode.

What is the Observer Model

The observer pattern is the object's behavior pattern, also known as Publish/Subscribe, Model/View, Source/Listener or Dependents.

When there is a one-to-many relationship between objects, the observer pattern is suitable. When an object is modified, its dependent object is automatically notified. The observer model belongs to the behavioral model.

For example, after the successful payment of the order, it may reduce the inventory of goods, calculate the membership points, notify the logistics delivery and so on.

Some concepts in the observer model

  • Observable Observed
  • Observer Observer

If you abstract the example just given into an observer pattern, it should be like this.

image.png

Java API

Java provides us with two API s, Observable and Observer, which can be used to extend the implementation of the observer pattern.

The observer interface is simple. When the observer changes, all observers are notified through the update method.

public interface Observer {
    void update(Observable o, Object arg);
}

Observed code, a little more, but it is not complicated. JDK provides us with a thread-safe observer model

public class Observable {
    private boolean changed = false;
    // Collection of observers
    private Vector<Observer> obs;

    public Observable() {
        obs = new Vector<>();
    }

    // Observer subscription
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    // Observers cancel subscriptions
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

    // Notify all observers
    public void notifyObservers() {
        notifyObservers(null);
    }

    // Notify all observers
    public void notifyObservers(Object arg) {
        Object[] arrLocal;

        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }
    
    // Changes in the observee
    protected synchronized void setChanged() {
        changed = true;
    }

    protected synchronized void clearChanged() {
        changed = false;
    }

    public synchronized boolean hasChanged() {
        return changed;
    }

    public synchronized int countObservers() {
        return obs.size();
    }
}

Realization

Xiao Li Zi: Push it to all subscribers when publishing articles by public number

/**
 * Public Number
 * (Observed)
 */
class OfficialAccount extends Observable {
    // Publish articles
    public void publishArticle(String article) {
        setChanged();
        notifyObservers(article);
    }
}
/**
 * user
 * (Observer)
 */
class User implements Observer {
    private String username;

    User(String username) {
        this.username = username;
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("Users:" + username + ", Received subscription articles:" + arg);
    }
}
public class Run {
    public static void main(String[] args) {
        OfficialAccount officialAccount = new OfficialAccount();
        User ytw = new User("ytw");
        User hmj = new User("hmj");
        officialAccount.addObserver(ytw);
        officialAccount.addObserver(hmj);
        officialAccount.publishArticle("SpringBoot");
        officialAccount.publishArticle("Java Understanding the Observer Model");
    }

}

Github portal

A little understanding

When learning the observer model, it always feels very similar to producer and consumer, both of which are well decoupled. The above observer model, if there are many subscribers, is inefficient (because it is synchronous). Individual understanding of the producer-consumer model is a variant of the observer model. Producer-consumer mode adds buffer queues, which can achieve good asynchronous message throughput.

Posted by engelsol on Thu, 01 Aug 2019 01:27:38 -0700