Copyright belongs to the author, any form of reprint please contact the author to obtain authorization and indicate the source.

What is the observer model and its definition

The observer pattern defines a one-to-many dependency that allows multiple observer objects to listen to a topic object at the same time and notify all observer objects when the topic object changes in state so that they can update themselves automatically.

The composition of the observer pattern

The observer mode is mainly composed of the following four roles: abstract subject role, abstract observer role, concrete subject role and concrete observer role.

Abstract Theme role

Keep references to all observer objects in a collection. Each abstract topic role can have any number of observers. Abstract topics provide an interface to add and remove observer roles, usually implemented in an abstract class or interface.

Abstract observer role

Define an interface for all specific observers to update themselves when notified of a topic.

Specific thematic roles

All registered observers are notified when state changes within a specific topic, and the specific topic role is usually implemented in a subclass.

Specific observer role

This role implements the update interface required by the abstract observer role to harmonize its state with that of the topic, and the specific observer role can have a reference to the specific topic role if needed, usually implemented as a subclass

Code example of observer pattern

Abstract theme roles:

public interface AbstractSubject {
    public void addObserver(AbstractObserver observer);
    public void removeObserver(AbstractObserver observer);
    public void notification();
}
Copy the code

Specific theme roles:

public class ConcreteSubject implements AbstractSubject {
    List<AbstractObserver> list = new ArrayList<AbstractObserver>();
    @Override
    public void addObserver(AbstractObserver observer) {
        list.add(observer);
    }
    @Override
    public void removeObserver(AbstractObserver observer) {
        list.remove(observer);
    }
    # State changes, all observers update their own interface
    @Override
    public void notification() {
        for(AbstractObserver abstractObserver : list) { abstractObserver.update(); }}}Copy the code

Abstract Observer role:

public interface AbstractObserver {
    public void update();
}
Copy the code

The test class

class Client {
    public static void main(String[] args) {
       Generate a theme character
        AbstractSubject subject = new ConcreteSubject();
        # Add an observer object for the theme role, using an anonymous inner class, similar to installing listeners in AWT programming
        subject.addObserver(new AbstractObserver() {
            @Override
            public void update() {
                System.out.println("Student A, your APP needs to be updated."); }}); subject.addObserver(newAbstractObserver() {
            @Override
            public void update() {
                System.out.println("B, your APP needs to be updated."); }}); subject.addObserver(newAbstractObserver() {
            @Override
            public void update() {
                System.out.println("C, your APP needs to be updated."); }}); subject.notification(); }}Copy the code

Java’s built-in observer pattern framework

The Java built-in Observer schema framework provides the Observable class and the Observer interface:

The Observable class corresponds to abstract subject roles, and internally maintains a Vector collection to store the abstract Observer roles corresponding to the interface Observer

According to the above description, how to implement an observer pattern based on Java’s built-in observer pattern framework?

  1. To write a class that inherits Observable (abstract subject role), write a change method that notifies registered subject roles to update themselves
  2. Write a class that implements the Observer (Observable O, Object ARG)
  3. Write a test class to test

Code demonstration

Specific theme roles:

public class Watched extends Observable {
    Call the update method of registered observers when their status changes and let them update themselves
    public void count(int number) {
        for (; number >= 0; number--) {
            try {
                Thread.sleep(1000);
                # Change notification
                setChanged();     
                 # notify all observers associated with menotifyObservers(number); } catch (Exception e) { e.printStackTrace(); }}}}Copy the code

Specific observer role:

public class Watcher implements Observer {
    The update method of all registered observer roles is called when the subject role event is triggered@Override public void update(Observable o, Object arg) { int number = (Integer) arg; System.out.println(number); }}Copy the code

The test class:

public class Client {
    public static void main(String[] args) {
        # Create theme roles
        Watched watched = new Watched();
        Create observer role
        Observer watcher1 = new Watcher();
        # the implementation
        Observer watcher2 = new Observer() {
            @Override
            public void update(Observable o, Object arg) {
                int number = (Integer) arg;
                if (0 == number) {
                    System.out.println("done"); }}}; watched.addObserver(watcher1); watched.addObserver(watcher2); watched.count(10); }}Copy the code

Summary of the Java Observer Pattern framework

  • The observed inherits the Observable class
  • When observers notifyObservers, namely, notifyObservers, setChanged() must be called first, This method sets the changed Boolean variable in this object to true, because notifyObservers first check that this variable is true, and if it is false, they do not execute and return it.
  • Observers include two overloaded notifyObservers, the one with parameters that is the second parameter in the Update method in the Observer interface.notifyObservers(number);The number variable argument is actually passed to the Observer interfaceupdate(Observable o, Object arg)In the second parameter arg.