GitHub JavaKeeper, contains N line Internet development skills essential weapon spectrum

There is often a requirement in software systems that if the state of an object changes, some of its related objects should also change accordingly.

  • Wechat official account. If a user subscribs to an official account, he will receive messages from the official account. The official account is the “observed”, and the user is the “observer”.
  • The weather station can publish the daily predicted temperature, humidity, pressure and so on to various third-party websites in the form of announcement. If there is any update of weather data, it should be able to inform the third party in real time. The meteorological bureau here is the “observed”, and the third-party website is the “observer”.
  • The relationship between model and view in MVC pattern also belongs to observation and being observed

The observer pattern is one of the most frequently used design patterns.

The observer mode includes two types of objects: the observation target and the observer. A target can have any number of dependent observers. Once the state of the observation target changes, all the observers will be notified.

define

Observer Pattern: Defines a one-to-many dependency between objects so that when each object changes state, all dependent objects are notified and updated automatically.

The observer pattern is an object behavior pattern.

The aliases for the observer pattern include Publish/Subscribe, Model/View, Source/Listener, or Dependents.

On closer inspection, publish-subscribe and observer are somewhat different, which can be interpreted as publish-subscribe in the broad sense of observer.

role

  • Subject: The observed, which means the object being observed. As you can see from the class diagram, the class has a Vector that holds the observer object (we use a Vector instead of a List because vectors are safe for multithreaded operations, whereas lists are not). This Vector is the core of the observed class, and there are three methods: The attach method adds an observer to the container; The detach method removes the observer object from the container; The notify method calls the corresponding methods of the observer objects in turn. This role can be an interface, an abstract class, or a concrete class, because in many cases it will be mixed with other patterns, so the use of abstract classes is more common.

  • ConcreteSubject: A concrete target is a subclass of the target class, usually containing frequently changing data that notifies its various observers when its state changes. It also implements the abstract business logic methods (if any) defined in the target class. If the target class is not extended, the concrete target class can be omitted.

  • Observer: An Observer reacts to changes in the object of observation. An Observer is generally defined as an interface that declares the method update() for updating data. Therefore, it is called an abstract Observer.

  • ConcreteObserver: In the ConcreteObserver, a reference to the ConcreteObserver is maintained. It stores the ConcreteObserver states that correspond to the ConcreteObserver states. It implements the update() method defined in the abstract Observer Observer. It is usually implemented by calling the attach() method of the concrete target class to add itself to the target class collection or by detach() method to remove itself from the target class collection.

The class diagram

Again record the UML class diagram notes, here my Subject is abstract method, so use *** italics, abstract method also use italics, specific various arrow meaning, I have also summarized before “Design pattern prequel — You should know these before learning design pattern” (has been poisoned by a variety of online postings of their own, Write it down carefully.

The instance

1. Define the observer interface

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

2. Define the observed

abstract class Subject {
    private Vector<Observer> obs = new Vector();

    public void addObserver(Observer obs){
        this.obs.add(obs);
    }
    public void delObserver(Observer obs){
        this.obs.remove(obs);
    }
    protected void notifyObserver(a){
        for(Observer o: obs){ o.update(); }}public abstract void doSomething(a);
}
Copy the code

3. The specific observed

class ConcreteSubject extends Subject {
    public void doSomething(a){
        System.out.println("Observed events change.");
        this.notifyObserver(); }}Copy the code

4. The specific observed

class ConcreteObserver1 implements Observer {
    public void update(a) {
        System.out.println("Observer 1 receives the message and processes it."); }}class ConcreteObserver2 implements Observer {
    public void update(a) {
        System.out.println(Observer 2 receives the message and processes it.); }}Copy the code

5. Client

public class Client {
    public static void main(String[] args){
        Subject sub = new ConcreteSubject();
        sub.addObserver(new ConcreteObserver1()); // Add observer 1
        sub.addObserver(new ConcreteObserver2()); // Add observer 2sub.doSomething(); }}Copy the code

The output

The observed event changes observer 1 receives the message and processes it Observer 2 receives the message and processes itCopy the code

As you can see from the run results, only the Subject’s methods are called, but the relevant methods of both observers are called at the same time. Taking a closer look at the code, it’s as simple as associating the Observer class in the Subject class and iterating through the Observer Update () method in the doSomething() method.

The advantages and disadvantages

advantages

  • The coupling relationship between the target and the observer is abstract
  • A set of triggers is established between the target and the observer
  • Support broadcast communication
  • In line with the “open and close principle” requirements

disadvantages

  • The dependency between target and observer is not completely removed, and circular references are possible
  • When there are many observers, the presentation of notifications takes a lot of time, affecting the efficiency of the program

application

Observer mode in the JDK

The Observer pattern plays an important role in the Java language. The Java.util package in the JDK provides the Observable class and Observer interface, which make up the JDK’s support for the Observer mode. But is deprecated in Java9.

The Observer pattern in Spring

The Spring event-driven model is also a classic application of the Observer pattern. Is the most common event listener in our common project.

1. Four roles for the Observer mode in Spring

  1. Event: ApplicationEvent is the parent class of all event objects. ApplicationEvent inherits from EventObject in the JDK. All events need to inherit ApplicationEvent and get the event source from source.

    Spring also provides us with a lot of built-in events, ContextRefreshedEvent, ContextStartedEvent, ContextStoppedEvent, ContextClosedEvent, RequestHandledEvent.

  2. EventListener: ApplicationListener, that is, observer, inherits from EventListener in the JDK, which has only one method onApplicationEvent. This method is executed when a listening event occurs.

  3. Event source: ApplicationContext. ApplicationContext is the core container in Spring. In event listening, the ApplicationContext can act as the event publisher, that is, the event source. Because the ApplicationContext inherited from ApplicationEventPublisher. Defines the method of event publishing: in ApplicationEventPublisher publishEvent (Object event)

  4. Event management: ApplicationEventMulticaster, used for event listener registration and broadcasting of events. It is used to register listeners by broadcasting events published by Applicationcontext to its list of listeners.

2. coding~~~~~~

1. Define events

public class MyEvent extends ApplicationEvent {
    public MyEvent(Object source) {
        super(source);
        System.out.println("my Event"); }}Copy the code

2. Implement event listeners

@Component
class MyListenerA implements ApplicationListener<MyEvent> {
    public void onApplicationEvent(MyEvent AyEvent) {
        System.out.println("ListenerA received"); }}@Component
class MyListenerB implements ApplicationListener<MyEvent> {
    public void onApplicationEvent(MyEvent AyEvent) {
        System.out.println("ListenerB received"); }}Copy the code

3. Event publishers

@Component
public class MyPublisher implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
    }
    
    public void publishEvent(ApplicationEvent event){
        System.out.println("publish event"); applicationContext.publishEvent(event); }}Copy the code

4. Test by annotating MyPublisher into Spring

@Configuration
@ComponentScan
public class AppConfig {

    @Bean(name = "myPublisher")
    public MyPublisher myPublisher(a){
        return newMyPublisher(); }}Copy the code
public class Client {

    @Test
    public void main(a) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        MyPublisher myPublisher = (MyPublisher) context.getBean("myPublisher");
        myPublisher.publishEvent(new MyEvent(this)); }}Copy the code

5, output,

my Event
publish event
ListenerA received
ListenerB received
Copy the code

ithe

Design mode is really just a design idea. You don’t have to have multiple observers to use the observer mode.

For chestnuts, again I do advertising (advertising goods generally for the XML file), if I had some free advertising space traffic, this I have to use up, so I just from taobao guest or spell evening evening on a lot of guests through open API access to some, this time I can also use the observer pattern, each request 100000 goods, I will generate a new commodity file, this time I can also use the observer mode, the class to get the commodity is the observed, write the commodity file is the observer, when there are 100,000 commodities, I will notify the observer to write a new file.

The big guys may feel that it’s a bit hard to implement this way. No matter you don’t have to design patterns or use message queues, it’s just a means to choose what suits your business and be happy.

reference

The design – patterns. Readthedocs. IO/zh_CN/lates…

www.cnblogs.com/jmcui/p/110…