Stop programming for for loops, the observer mode that comes with JDK is very fragrant

Hi everyone, are you still programming for for loops?

 

Who else can't use the observer pattern?

This article brings the theory and actual combat of " Observer Mode "~

What is the Observer Pattern?

The Observer Pattern defines a one-to-many dependency between objects, so that as long as the state of an object changes, all related objects it depends on will be notified and automatically updated.

In the observer mode, the object that changes is called the observation target , and the object that is notified of the update is called the observer . One observation target corresponds to multiple observers. The observers are generally a list collection, which can be dynamically added and deleted as needed. Easy to expand.

The advantage of using the observer pattern is that there is an abstract loose coupling relationship between the observation target and the observer, which reduces the coupling relationship between the two.

publish-subscribe model

Observer mode is also called publish-subscribe mode (Publish/Subscribe) in many places. In fact, it can be understood in this way, but there are still slight differences between the two.

The observer in the observer mode is directly bound to the observation target, and the observation target needs to maintain a set of observer lists. The two have a combined dependency based on the interface. Therefore, although the observer mode is loosely coupled, it is not Not completely decoupled.

In the publish-subscribe model, there is no connection between the publisher and the subscriber. The publisher publishes a topic (Topic) through the middle party, and the subscriber subscribes to a topic (Topic) through the middle party (scheduling center), and the publisher status The changes of the subscribe will not be notified directly to the subscribers, but will be notified through the intermediary, or the subscribers will pull from the intermediary by themselves, so the publish-subscribe model is completely decoupled.

A picture to understand their relationship:

The difference between the observer pattern and the subscription-publishing pattern

From the pictures, there are differences between the two. They are both called the observer mode, and there is nothing wrong with them.

Observer mode wheel

Because the observer mode is widely used, the JDK toolkit comes with the observer mode template set from version 1.0. We can easily implement the observer mode according to its template, and there is no need to repeat the wheel.

Observer target class:

java.util.Observable

The two most important variables are:

  • changed : Observe whether the target state has changed, the default is: false;
  • obs : Observer list (observers), a thread-safe list collection: Vector, the default is an empty collection;

The important methods in it are all related to the state of the observation target and the observer. It is clear at a glance and will not be introduced here.

Observer interface:

java.util.Observable

public interface Observer {
    /**
     * This method is called whenever the observed object is changed. An
     * application calls an <tt>Observable</tt> object's
     * <code>notifyObservers</code> method to have all the object's
     * observers notified of the change.
     *
     * @param   o     the observable object.
     * @param   arg   an argument passed to the <code>notifyObservers</code>
     *                 method.
     */
    void update(Observable o, Object arg);
}

The observer interface has only one update method, which is used to notify the observer to update itself.

Observer mode in action

OK, knowing that the JDK comes with these two things, now let's implement a simple application scenario of the observer mode, simulating the push of articles on the official account, the observation target is me, the observer is all of you, and I am in the public No. Java technology stack pushes an article, you can all receive the update notification and can read it.

New observation target class:

import lombok.Getter;

import java.util.Observable;

/**
 * 观察目标:栈长
 * 来源微信公众号:Java技术栈
 */
@Getter
public class JavaStackObservable extends Observable {

    private String article;

    /**
     * 发表文章
     * @param article
     */
    public void publish(String article){
        // 发表文章
        this.article = article;

        // 改变状态
        this.setChanged();

        // 通知所有观察者
        this.notifyObservers();
    }

}

The logic of the observation target is to publish the article first, then change the state of the observation target, and then notify all observers.

Let's focus on the source code of the notifyObservers method:

First acquire the synchronization lock, determine whether the state is updated, if it has been updated, clear the observation target state, then use the for loop to traverse all the observers, and call the update method of the observer to notify the observer to update.

Add an observer class:

import lombok.NonNull;
import lombok.RequiredArgsConstructor;

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

/**
 * 观察者:读者粉丝
 * 来源微信公众号:Java技术栈
 */
@RequiredArgsConstructor
public class ReaderObserver implements Observer {

    @NonNull
    private String name;

    private String article;

    @Override
    public void update(Observable o, Object arg) {
        // 更新文章
        updateArticle(o);
    }

    private void updateArticle(Observable o) {
        JavaStackObservable javaStackObservable = (JavaStackObservable) o;
        this.article = javaStackObservable.getArticle();
        System.out.printf("我是读者:%s,文章已更新为:%s\n", this.name, this.article);
    }

}

The logic of the observer is to obtain the observer target instance object, then update the article information of the observer target object to its own article information, and finally output that the article of so-and-so has been updated.

The observer only needs to implement the update method of the Observer interface, which is used to observe the target for call notification.

All the actual source code of this tutorial has been uploaded to this repository: https://github.com/javastacks/javastack

The observation target and observer class structure diagram is as follows:

New exam classes:

/**
 * 观察者:读者粉丝
 * 来源微信公众号:Java技术栈
 */
public class ObserverTest {

    public static void main(String[] args) {
        // 创建一个观察目标
        JavaStackObservable javaStackObservable = new JavaStackObservable();

        // 添加观察者
        javaStackObservable.addObserver(new ReaderObserver("小明"));
        javaStackObservable.addObserver(new ReaderObserver("小张"));
        javaStackObservable.addObserver(new ReaderObserver("小爱"));

        // 发表文章
        javaStackObservable.publish("什么是观察者模式?");
    }

}

There is no sequence requirement for the creation of observation targets and observers. The key point is that before publishing articles to notify the observers, the observation target must be added to the observer list.

Output result:

Through this simple article push practice, everyone should have a basic understanding of the observer pattern. In actual work, there are many scenarios that can be used, and the observer pattern can be considered for one-to-many dependencies.

Summarize

It's not easy. After working for a long time one after another, have you learned the observer mode?

The advantage of the observer pattern is to decouple the observation target and the observer, and the disadvantage is also obvious. It can be seen from the above example that if there are too many observer objects, it may cause memory leaks.

In addition, from the perspective of performance, the updates of all observers are queued in a loop, so the update operation of the observers can be considered as asynchronous threads (or thread pools can be used) to improve the overall efficiency.

All the actual source code of this tutorial has been uploaded to this repository:

https://github.com/javastacks/javastack

Guess you like

Origin blog.csdn.net/m0_63437643/article/details/123774254