In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article focuses on "how Guava and Spring abstract the observer pattern". Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how Guava and Spring abstract the Observer pattern.
What is the Observer Mode?
Observer pattern is a behavioral design pattern, which allows you to define a subscription notification mechanism, which can notify multiple observer objects that "observe" the object when an object (observed) event occurs, so it is also called publish subscription pattern.
In fact, personally, I don't like to use words to define the semantics of a design pattern, because it is always difficult to understand. So there are the following examples in life to help readers better understand the semantics of patterns. The class diagram is as follows:
Before giving an example, let's familiarize ourselves with the role types and code examples in Observer mode. The observer pattern consists of the following roles, which can be understood by referring to the code examples and should not be biased by the text description.
Topic (observed) (Subject): abstract subject roles store all observer objects in a container, provide interfaces for adding and removing observers, and provide interface for notifying all observers (also described by authors through Observable)
Specific topic (specific observed) (Concrete Subject): the responsibility of a specific subject role is to implement the interface semantics of the abstract target role, and to send status notifications to all registered observers in the container when the state of the observed changes.
Public interface Subject {void register (Observer observer); / / add Observer void remove (Observer observer); / / remove Observer void notify (String message); / / notify all observers of events} public class ConcreteSubject implements Subject {private static final List observers = new ArrayList (); @ Override public void register (Observer observer) {observers.add (observer);} @ Override public void remove (Observer observer) {observers.remove (observer) @ Override public void notify (String message) {observers.forEach (each-> each.update (message));}}
Abstract observer (Observer): the abstract observer role is the abstraction of the observer's behavior, which defines a modification interface that notifies itself when the observer emits an event.
Concrete observer (Concrete Observer): implements an update interface defined by the abstract observer, which can notify yourself when the observer emits an event
Public interface Observer {void update (String message); / / String input parameter is just an example. Real business will not restrict} public class ConcreteObserverOne implements Observer {@ Override public void update (String message) {/ / execute message logic System.out.println ("received observer status change-1") }} public class ConcreteObserverTwo implements Observer {@ Override public void update (String message) {/ / execute message logic System.out.println ("received observer status change-2");}}
Let's run the observer mode example above and print out the logs in the execution logic of the two observers if nothing happens. If it is ordinary business logic, the input parameter defined by the abstract observer is of business significance. You can compare the MQ Message mechanism used in the project.
Public class Example {public static void main (String [] args) {ConcreteSubject subject = new ConcreteSubject (); subject.register (new ConcreteObserverOne ()); subject.register (new ConcreteObserverTwo ()); subject.notify ("change in the state of the observed, notify all registered observers");}} Observer mode combines business
Because the company's business scene is confidential, so let's slightly tamper with the plot of the movie "New Police Story" to simulate our observer mode application scenario.
Suppose: at present, we have three policemen, namely, Brother long, Brother Feng and Lao San, who have been ordered to follow up on the suspect Ah Zu. If the suspect Ah Zu is found to have any movement, Brother long and Brother Feng are responsible for carrying out the arrest operation, and the third brother shakes people to the police station. The flow chart is as follows:
If you use conventional code to write this set of processes, you can achieve the requirements, a shuttle of logic can achieve all the requirements. However, if we say that the next action, Brother long let the third follow him to carry out the arrest, or that is to say, the team of Brother long expands, there are four, five and six.
Compared with the role definition of the observer model, the fourth, fifth and sixth are all specific observers (Concrete Observer).
What would be the problem if we wrote the code in a "shuttle" way as envisioned above? As follows:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
Bear the brunt, increasing the complexity of the code. The implementation class, or this method function, is extremely large, because as the police officer expands, the code block will become larger and larger.
It violates the principle of opening and closing, because the tasks of different police officers will be changed frequently. The task of every police officer is not immutable. For example, the arrest of the suspect and Brother Feng may be evacuated next time. Do you need to change the "shuttle" code every time?
First, we can solve the problem of code responsibility by splitting a large function into a small function or a large class into small classes. However, the principle of opening and closing cannot be avoided, because with the increase and decrease of police officers (observers), they are bound to face frequent changes to the original function.
When we are faced with this kind of code which is known to change and may change frequently, we should use abstract thinking to design so as to keep the code concise and maintainable.
Here the Java SpringBoot project structure is used to write the observer pattern, and the code is eventually pushed to the Github repository. Readers can pull down the warehouse first, because it includes not only the sample code, but also the Guava and Spring's observer pattern implementation GitHub warehouse address.
First of all, the observer role in the observer pattern is defined as the abstract observer interface and three concrete observer implementation classes. In practice, the design pattern is combined with the Spring framework, so the sample code contains Spring-related annotations and interfaces
Secondly, the abstract observed interface and the concrete observed implementation class are defined. As above, the observed also needs to be a Spring Bean, hosted in IOC container management
At this point, a complete observer model is complete. However, careful readers will find that there is a small problem with such an observer model. Without explanation here, move on. Then you need to do some practical practice, register these observers, and notify the observers by triggering events by the observer.
How to realize the principle of opening and closing
After looking at the code of the application, the problem of too large function body has been solved, and we split the overall logic by splitting into different concrete observer classes. But what about the principle of opening and closing? This is the problem mentioned above. At present, we are adding to the notification container of the observed by introducing a specific observer mode through the display, and if we later add the fourth and fifth policemen. When more and more police officers still need to change the original code, how should the problem be solved?
In fact, it is very simple. Usually Web projects are basically developed using the Spring framework, so it is natural to use the features in it to solve scene problems. Here, we realize the opening and closing principle by transforming the specific observer.
If you have read the design pattern article written by the author before, you will not be unfamiliar with the InitializingBean interface. In the afterPropertiesSet method, we get all the observer objects through the injected IOC container and add them to the observed notification container. In this case, the observer event is triggered, and only one line is needed in the code to complete the notification.
@ PostConstruct public void executor () {/ / the event triggered by the observer notifies all observers of the subject.notify ("Azu has action!") ;}
If a new observer class is added later, you only need to create a new class to implement the abstract observer interface to complete the requirement. Sometimes, not only DateUtil-type tool classes can be encapsulated, but also some design patterns can be encapsulated so that better service developers can use them flexibly. The Guava#EventBus and Spring# event models are introduced here, respectively.
The concept of synchronization and asynchrony
Before introducing the EventBus and Spring event models, there is an insurmountable bend, that is, the concept of synchronous and asynchronous execution, and in what scenarios do you use synchronous and asynchronous models?
Synchronous execution: synchronous execution means that after a request is made, the caller waits in the current code before getting the result of the call. It is not finished until the execution result of the calling method is obtained. To sum up, it is up to the caller to wait for the result of this call and do nothing else until it is returned.
Asynchronous execution: asynchronous execution, on the contrary, returns as soon as the call request is made, and executes the code down. In general, asynchronous calling methods do not return results, and other operations can be performed after the call. Callers are generally notified of the results by callback functions.
Here to give you an example, can well reflect the concept of synchronization, asynchronous. For example, if you want to call the medical examination hospital to make an appointment, after you say the time you want to make an appointment, the little sister opposite says, "wait a minute, I'll check if the time is all right." if you don't hang up at this time, wait for the little sister to check and tell you before hanging up the phone, then this is synchronization. If she says she needs to check it later, you tell her, "I'll hang up first. I'll call back when I get the result." then this is async + callback.
In the sample code we wrote above, there is no doubt that the observer pattern is executed in the form of synchronization, so can the observer behavior be performed asynchronously? Of course the answer is yes. We can create a thread before the observer mode behavior is executed, which is naturally asynchronous. Of course, it is not recommended that you do so, which may lead to more problems. Let's take a look at how Guava and Spring encapsulate the Observer pattern.
Guava EventBus parsing
EventBus is a message publish-subscribe class library provided by Google Guava. It is a classic implementation of the observer pattern (production / consumer model) in the design pattern.
The specific code has been uploaded to the GitHub code repository. Synchronous and asynchronous modes are included in the EventBus implementation, and the observer mode is implemented synchronously in the code base.
Because EventBus is not the focus of the article, I will only discuss its principle here. First of all, EventBus is a synchronous class library. If you need to use asynchronous, specify AsyncEventBus when you create it.
/ / create synchronous EventBus EventBus eventBus = new EventBus (); / / create asynchronous AsyncEventBus EventBus eventBus = new AsyncEventBus (Executors.newFixedThreadPool (10))
Note that creating an AsyncEventBus requires a thread pool, which is not specified by default. Of course, unlike the above code created directly with Executors, the author is to save trouble, if from the specification, or stop using the default thread pool build method to create new ThreadPoolExecutor (xxx)
The EventBus synchronization implementation has an interesting point. When the observer operates synchronous and asynchronous behavior, they all use Executor to execute the internal code of the observer, so how to ensure that Executor can be executed synchronously. Guava does this: implement the Executor interface, override the execution method, and call the run method
Enum DirectExecutor implements Executor {INSTANCE; @ Override public void execute (Runnable command) {command.run ();}}
If you are interested, you can take a look at the EventBus source code, it is not very difficult to understand, the work is still very convenient to use. It's just that there are some disadvantages, because EventBus is an in-process operation, and if you use asynchronous AsyncEventBus to perform business, it is possible to lose tasks.
Spring event model
The Observer pattern abstraction of Spring Master Design is the most elegant and functional design the author has ever seen. If you want to play with the Observer pattern recommendation Index?
If you want to use ApplicationEvent to play observer mode, you only need a few simple steps. Summary: easy to operate and powerful
To create a business-related MyEvent, you need to inherit ApplicationEvent and override the parameter constructor
Define different listeners (observers) such as ListenerOne implements the ApplicationListener interface and overrides the onApplicationEvent method
Publish specific events through the ApplicationContext#publishEvent method
The Spring event is the same as Guava EventBus, where the code is not pasted and is stored in the Github code repository. This paper focuses on the characteristics and usage of the Spring event model.
The Spring event also supports asynchronous programming, and you need to add the @ Async annotation to the concrete Listener implementation class. Support the order of Listener subscriptions, for example, there are A, B, C three Listener. Multiple observers can be consumed sequentially through @ Order annotations
The author suggests that readers be sure to run off ApplicationEvent's Demo and make reasonable use of the tool wheels provided by the framework while using the framework, because the functions encapsulated by the framework are generally more powerful and less likely to have problems than those written by themselves. At the same time, remember not to build repetitive wheels. Unless the function points are not satisfied, you can develop your own functions on the basis of the original wheels.
At this point, I believe you have a deeper understanding of "how Guava and Spring abstract the Observer pattern". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.