There are feelings, there are dry goods, wechat search [three prince Ao bing] pay attention to the programmer who has a little bit of things.

This article has been included in GitHub github.com/JavaFamily, there are a line of large factory interview complete test sites, information and my series of articles.

Message queue (MQ), a communication model that implements one-way producer-to-consumer communication, is also the mainstream middleware used today. RabbitMQ, ActiveMQ, Kafka, etc. They also have many advantages such as decoupling, asynchronous, broadcast, peak clipping, etc.

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 publish and subscribe pattern.

Today a c to share the actual development of the more common this model

The outline

define

What is the observer model? What is his aim?

When an object’s state changes, other registered objects can observe the change and make their own changes. In this way to achieve the reduction of dependency, decoupling of the role.

For example, wechat circle of Friends takes the current individual as the subscriber and friends as the theme. When a person posts a post in his/her “moments”, all his/her friends can see it and choose to like or comment on it.

It feels a bit abstract, but look at some of his main characters:

  • Subject: An observable interface implemented primarily by a class, notifying the observer to use the Attach method, and the detach method to unobserve.
  • ConcreteSubject: A class that implements a topic interface that handles observer changes
  • Observe: An observer is an interface to the water bank of an object, updated according to changes in the topic.

This view of the role is not much, but the feeling is still a bit abstract, we still use the concrete example code to walk again, we still above the circle of friends as an example to see the code implementation

public interface Subject {
    // Add a subscription
    void attach(Observer observer);
    // Remove the subscription
    void detach(Observer observer);
    // Notify subscribers
    void notifyObservers(String message);
}
Copy the code

Start by creating a topic definition that defines add and remove relationships and notifies subscribers

public class ConcreteSubject implements Subject {

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

    @Override
    public void attach(Observer observer) {
        // Add a subscription
        observers.add(observer);
    }

    @Override
    public void detach(Observer observer) {
        // Remove the subscription
        observers.remove(observer);
    }

    @Override
    public void notifyObservers(String message) {
        // Notify subscribers
        for(Observer observer : observers) { observer.update(message); }}}Copy the code

A specific topic is then created, and a container is built to maintain subscriptions, support adding and removing relationships, and notify subscribers

public interface Observer {
    // Process the business logic
    void update(String message);
}
Copy the code

Create an observer interface for us to manage

public class FriendOneObserver implements Observer {
   
  @Override
    public void update(String message) {
        // Simulate processing business logic
        System.out.println("FriendOne knows about your twitter feed."+ message); }}Copy the code

The last step is to create a concrete observer class that implements the Update method of the observer interface and handles its own business logic

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

        ConcreteSubject subject = new ConcreteSubject();
        // Add a friend
        subject.attach(new FriendOneObserver());
        FriendTwoObserver twoObserver = new FriendTwoObserver();
        subject.attach(twoObserver);

        // Send a message to your moments
        subject.notifyObservers("The first instant message");
        FriendOne knows that you sent the first instant message
        // FriendTwo knows you sent your first wechat message

        // twoObserver is recommended to sell tea
        subject.detach(twoObserver);
        subject.notifyObservers("Second moments message");
        // Result: FriendOne knows that you sent a second instant message}}Copy the code

Finally, there is the test result, which is that a subscription is maintained with ConcreteSubject, and after notifyObservers of subscribers through notifyObservers, they are receiving messages to process their business logic.

The careful friend here has achieved the effect of understanding the coupling while reducing dependencies, so that each observer does not have to know what business logic the publisher handles, nor does it have to rely on any business model of the publisher, but only cares about the logic it needs to handle.

If new business is added, all we need to do is create a new subscriber and maintain it in the observers container, consistent with our open-close principles.

This is just one synchronous implementation, but we can extend other asynchronous implementations, or use multithreading.

Application framework

The observer pattern should also be used extensively in frameworks

  • The first person familiar with the JDK should know that the java.util package includes an Observable class in addition to the common collections and maps, which is implemented in observer mode. There are also ways to add, delete, and notify.

    It should be noted here that Vector is used as a container for subscriptions, and synchronized keyword modifier classes are added to its definition methods to achieve the purpose of thread safety

    I’ve posted the key source code here, so interested students can open it for themselves and view the comments for each method.

  • The second, In Spring have a ApplicationListener, also is the observer pattern is used to deal with, ApplicationEventMulticaster as a theme, add, delete, etc.

    Spring has some built-in events, when the completion of certain operations will emit certain event actions, it is the above mode of processing, of course, there are many more, I did not go into detail, interested students can carefully understand the spring startup process.

import java.util.EventListener;

/**
 * Interface to be implemented by application event listeners.
 * Based on the standard {@codeJava.util.EventListener} interface * for the Observer design pattern. 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
 * @seeOrg. Springframework. Context. Event. ApplicationEventMulticaster * / / / theme
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

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

}
Copy the code
  • The third kind of event processing mechanism of Google Guava is Guava EventBus, whose implementation also adopts the observer design pattern of 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 easy use:

  • Register method as add observer

  • The unregister method deletes an observer

  • The POST method sends notification messages

It’s very convenient to use. Add the @subscribe annotation to create a subscriber. See our website for details.

Examples of real business transformation

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

After the successful registration of new users, we need to do two things for the users. The first is to send the message of successful registration, and the second is to send coupons for new users.

The first thing you might think of when you look at this problem is MQ messaging. Yes, you can do it with messages, but let’s do it in the observer mode and show you the synchronous or asynchronous problem.

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(a) throws Exception {
                TimeUnit.SECONDS.sleep(3);
                // Process the business logic of the response
                return Call the coupon service, return the result; }});try {
            // If no return value is obtained after 200 milliseconds, the result is considered as failure
            System.out.println(future.get(4000, TimeUnit.MILLISECONDS));
        } catch (Exception e) {
            // Failed to perform asynchronous fetch
            // Record logs and retry scheduled tasks
        }

        // The first does not care about the result of the return value
        Thread thread = new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run(a) {
                // Simulate the service calling thread to sleep for 3 seconds
                TimeUnit.SECONDS.sleep(3);
                System.out.println("Send coupons for new people."); }}); thread.start(); System.out.println("Perform an asynchronous return"); }}Copy the code
public class SendSuccessMessageObserver implements Observer {

    @Override
    public void update(String message) {
        // Process the business logic
        System.out.println("Registration successful");
    }

    public static void main(String[] args) {
        // Assume that the user succeeds in registering and notifies the observer directly to go about his or her own business
        ConcreteSubject subject = buildSubject();
        subject.notifyObservers("");
    }
 
   private static ConcreteSubject buildSubject(a) {
        ConcreteSubject subject = new ConcreteSubject();
        subject.attach(new SendSuccessMessageObserver());
        subject.attach(new SendNewPersonCouponObserver());
        returnsubject; }}Copy the code

Here we wrote two observers, basically see the first SendNewPersonCouponObserver, here the asynchronous open new thread to handle our business logic, when we are concerned about the return value could be obtained with the Future returns as a result, when you don’t care about the return value of a, Just start the normal thread.

This is a fairly simple example to illustrate asynchronous thread processing, which can also be done with Guava EventBus. And it is not complicated, interested friends can try.

There are now better middleware MQ message queues to handle this business problem, which makes us more comfortable with this kind of scenario, but some resources are not enough to introduce new systems. You can still do it this way.

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

conclusion

The observer pattern, as a behavioral design pattern, is also designed to decouple code from different business behaviors.

Rational use of design pattern can make the code structure more clear, but also to meet the different small modules in line with the single responsibility, and the principle of open and closed, so as to achieve the factory pattern described in the previous, improve the scalability of the code, low maintenance costs.

I’m Aobing, the more you know, the more you don’t know, thank you for your talent: likes, favorites and comments, we’ll see you next time!


This article is constantly updated. You can search “Santaizi Aobing” on wechat and read it for the first time. Reply [Information] There are the interview materials and resume templates for first-line big factories prepared by me.