Ali P6+ interview: introduce the observer mode?

With feelings and dry goods, WeChat search [ San Taizi Ao Bing ] pays attention to this programmer who has a little stuff.
This article has been included on GitHub https://github.com/JavaFamily , with the complete test sites, materials and my series of articles for interviews with major companies.

Message Queuing (MQ), a communication model that can realize one-way communication from producer to consumer, is also the mainstream middleware commonly used now. Common with RabbitMQ, ActiveMQ, Kafka and so they also have a lot of features such as de-coupling , asynchronous , broadcast , clipping , and so many advantages characteristics.

In the design pattern, there is also a pattern that can effectively achieve the characteristics of decoupling and asynchronous , that is, the observer pattern is also called the publish-subscribe pattern .

Today, Ah Bing will share this mode that is more common in actual development.

Outline

definition

What is the observer mode? What is his purpose?

When the status of an object changes, other registered objects can observe this change and make their own corresponding changes. In this way, the effect of reducing dependencies and decoupling is achieved.

For example, it is like WeChat Moments, with the current individual as the subscriber and the friend as the subject. When a person posts a dynamic circle of friends out, his friends can see the circle of friends, and can choose to like or comment on their own.

It feels a bit abstract, let’s take a look at his main roles:

  • Subject: The observable interface mainly implemented by the class, which informs the observer to use the attach method and the detach method to cancel the observation.
  • ConcreteSubject (specific subject): is a class that implements the subject interface and handles changes in observers
  • Observe (Observer): Observer is an interface by the object waterfront, updated according to the changes in the theme.

There are not many roles in this way, but it still feels a bit abstract. Let’s go through the specific example code. Let’s take the above circle of friends as an example to see the code implementation.

public interface Subject {
    // 添加订阅关系
    void attach(Observer observer);
    // 移除订阅关系
    void detach(Observer observer);
    // 通知订阅者
    void notifyObservers(String message);
}

First create a topic definition, define the relationship between adding and deleting and notifying subscribers

public class ConcreteSubject implements Subject {

    // 订阅者容器
    private List<Observer> observers = new ArrayList<Observer>();

    @Override
    public void attach(Observer observer) {
        // 添加订阅关系
        observers.add(observer);
    }

    @Override
    public void detach(Observer observer) {
        // 移除订阅关系
        observers.remove(observer);
    }

    @Override
    public void notifyObservers(String message) {
        // 通知订阅者们
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

Next, create a specific topic, and build a container to maintain the subscription relationship, support adding and deleting relationships, and notifying subscribers

public interface Observer {
    // 处理业务逻辑
    void update(String message);
}

Create an observer interface to facilitate our management

public class FriendOneObserver implements Observer {
   
  @Override
    public void update(String message) {
        // 模拟处理业务逻辑
        System.out.println("FriendOne 知道了你发动态了" + message);
    }
}

The last is to create a specific observer class, implement the update method of the observer interface, and process its own business logic

public class test {
    
    public static void main(String[] args) {

        ConcreteSubject subject = new ConcreteSubject();
        // 这里假设是添加好友
        subject.attach(new FriendOneObserver());
        FriendTwoObserver twoObserver = new FriendTwoObserver();
        subject.attach(twoObserver);

        // 发送朋友圈动态
        subject.notifyObservers("第一个朋友圈消息");
        // 输出结果: FriendOne 知道了你发动态了第一个朋友圈消息
        //          FriendTwo 知道了你发动态了第一个朋友圈消息

        // 这里发现 twoObserver 是个推荐卖茶叶的,删除好友
        subject.detach(twoObserver);
        subject.notifyObservers("第二个朋友圈消息");
        // 输出结果:FriendOne 知道了你发动态了第二个朋友圈消息
    }
}

Finally, look at the test results. A subscription relationship is maintained through ConcreteSubject. After the subscriber is notified through the notifyObservers method, the observers all get the message to process their own business logic.

The attentive friends here have achieved the effect of understanding the coupling, and at the same time reducing the dependency. Each observer does not need to know what business logic the publisher handles, and does not need to rely on any business model of the publisher, but only cares about the logic that he needs to handle. That's it.

If a new business is added, we only need to create a new subscriber and maintain it in the observers container, which is also in line with our opening and closing principles.

Here is just a synchronous implementation, we can also extend more other asynchronous implementations, or use multi-threading and other implementations.

Framework application

There should be many applications of the observer pattern in the framework

Those who are familiar with the JDK should know that there is an Observable class in addition to the commonly used collections and maps under the java.util package. Its implementation is actually the observer mode. There are also methods for adding, deleting, and notifying .

It should be noted here that he uses Vector as the container for the subscription relationship, and at the same time adds the synchronized keyword to modify the class in his definition method, in order to achieve the purpose of thread safety

Here I have posted the key source code, and interested students can open and watch the comments of each method.

The second type has an ApplicationListener in Spring, which is also handled in the observer mode, with ApplicationEventMulticaster as the theme, which contains addition, deletion, notification, etc.

Spring has some built-in events. When a certain operation is completed, certain event actions will be issued. His processing method is also the above mode. Of course, there are many more. I did not elaborate on it. Interested students can be careful. Understand the startup process of Spring.

import java.util.EventListener;

/**
 * Interface to be implemented by application event listeners.
 * Based on the standard {@code java.util.EventListener} interface
 *  for the Observer design pattern. // 这里也已经说明是采用观察者模式
 *
 * <p>As of Spring 3.0, an ApplicationListener can generically declare the event type
 * that it is interested in. When registered with a Spring ApplicationContext, events
 * will be filtered accordingly, with the listener getting invoked for matching event
 * objects only.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @param <E> the specific ApplicationEvent subclass to listen to
 * @see org.springframework.context.event.ApplicationEventMulticaster //主题
 */
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

Guava EventBus, the third Google Guava event processing mechanism , is also implemented using the observer design pattern in the design pattern.

EventBus is currently implemented in two ways:
  • EventBus // Synchronous blocking mode
  • AsyncEventBus // // Asynchronous non-blocking mode

EventBus also provides a series of methods for our convenience:

register method as an add observer

The unregister method deletes the observer

post method to send notification messages, etc.

It is very convenient to use. You can create a subscriber by adding @Subscribe annotation. Please check the official website for specific usage.

Examples of real business transformation

There are so many examples of framework applications, and there are actually many places that can be used in business scenarios. Here I will give you an example.

After the new user is successfully registered, we need to do two things for the user. The first is to send a successful registration message, and the second is to send a new user coupon to the user.

When you see this problem, you may first think of using MQ message processing, yes, it is indeed possible to use messages, but here we use the observer mode to achieve this problem, and at the same time, we can demonstrate to you the problem of synchronization or asynchronous.

public class SendNewPersonCouponObserver implements Observer {

    ExecutorService pool = Executors.newFixedThreadPool(2);

    @Override
    public void update(String message) {

        Future<String> future = pool.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                TimeUnit.SECONDS.sleep(3);
                // 处理响应的业务逻辑
                return "调用发券服务,返回结果";
            }
        });
        try {
            // 假设等待200毫秒 没有获取到返回值结果则认为失败
            System.out.println(future.get(4000, TimeUnit.MILLISECONDS));
        } catch (Exception e) {
            // 执行异步获取失败
            // 记录日志,定时任务重试等
        }

        // 第一种不关心返回值结果
        Thread thread = new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                // 模拟服务调用 线程睡3秒钟
                TimeUnit.SECONDS.sleep(3);
                System.out.println("发送新人优惠券");
            }
        });
        thread.start();
        System.out.println("执行异步返回");
    }
}
public class SendSuccessMessageObserver implements Observer {

    @Override
    public void update(String message) {
        // 处理业务逻辑
        System.out.println("注册成功");
    }

    public static void main(String[] args) {
        // 假设用户注册成功直接通知观察者,改干自己的事情了
        ConcreteSubject subject = buildSubject();
        subject.notifyObservers("");
    }
 
   private static ConcreteSubject buildSubject() {
        ConcreteSubject subject = new ConcreteSubject();
        subject.attach(new SendSuccessMessageObserver());
        subject.attach(new SendNewPersonCouponObserver());
        return subject;
    }
}

Here we have written two new observers, mainly looking at the first SendNewPersonCouponObserver, where we asynchronously start a new thread to process our business logic. When we care about the return value, we can use Future to get the return result, when we don’t care. To change the return value, just start the ordinary thread directly.

This example is actually relatively simple as a whole, mainly to clarify asynchronous thread processing, of course, it can also be achieved if Guava EventBus is used. And it's not complicated, and interested friends can try it by themselves.

At present, there are better middleware MQ message queues to deal with this business problem, which makes us more calmly face this kind of scene problem, but some resources are insufficient and we do not want to introduce a new system. It is still possible to deal with the problem in this way.

Design patterns do not learn code, but learn the ideas of each pattern, and what business scenarios they deal with.

to sum up

After reading this article, you don’t know if you have discovered it. In fact, the entire content is written around the idea of decoupling . The observer pattern, as a behavioral design pattern, is mainly for code decoupling of different business behaviors .

Reasonable use of design patterns can make the code structure clearer, and at the same time, it can also satisfy that different small modules comply with a single responsibility and open and close principles, so as to achieve the characteristics of the factory model written above, improve the scalability of the code, and low maintenance costs. .

This is Ao Bing. The more you know, the more you don’t know. See you in the next issue.


Ao Bing compiled his interview essays into an e-book with 1,630 pages!

Full of dry goods, the essence of every word. The content is as follows, as well as the interview questions and resume templates I summarized during the review, which are now given to everyone for free.

Link: https://pan.baidu.com/s/1ZQEKJBgtYle3v-1LimcSwg Password:wjk6

This is Ao Bing. The more you know, the more you don’t know . Thank you all for your praises , favorites and comments . See you in the next issue!


Article continually updated, you can search a search micro-channel " Third Prince Ao propionate " the first time to read, reply [ data ] first-tier manufacturers have interview data and I am ready to resume template, the paper GitHub https://github.com/JavaFamily already included , There are complete test sites for interviews with major factories, welcome to Star.