Five minutes to learn observer mode

Here Insert Picture Description

Introduction

Observer pattern: a plurality of viewers simultaneously monitor a theme object when the subject is the object changes, it's all observers will be notified.

Such as micro-channel public number, when the author issued a document, all subscribers will receive. Such observer mode can achieve broadcast, while in line with the principle of opening and closing, adding new viewers without changing the original code.

The observer pattern UML diagram below
Here Insert Picture Description
Subject (theme): defines the set of observers from registration, delete, notification observer method
ConcreteSubject (specific topic)
the Observer (observers): defines the theme changes made upon receipt of notification
ConcreteObserver (particularly observer)

Handwriting observer mode

To the public micro-channel number, for example to write an observer mode

Abstract theme

public interface MySubject {

    void registerObserver(MyObserver o);

    void removeObserver(MyObserver o);

    void notifyObserver();
}

Abstract observer

public interface MyObserver {
    void update(String authorName, String articleName);
}

Specific topics

public class WeChatServer implements MySubject {

    private List<MyObserver> myObservers;
    private String authorName;
    private String articleName;

    public WeChatServer(String authorName) {
        myObservers = new ArrayList<>();
        this.authorName = authorName;
    }

    public void publishArticle(String articleName) {
        this.articleName = articleName;
        notifyObserver();
    }

    @Override
    public void registerObserver(MyObserver o) {
        myObservers.add(o);
    }

    @Override
    public void removeObserver(MyObserver o) {
        if (myObservers.contains(o)) {
            myObservers.remove(o);
        }
    }

    @Override
    public void notifyObserver() {
        myObservers.forEach(item -> {
            item.update(authorName, articleName);
        });
    }
}

Specific observer

public class WeChatClient implements MyObserver {

    private String username;

    public WeChatClient(String username) {
        this.username = username;
    }

    @Override
    public void update(String authorName, String articleName) {
        System.out.println(username + ": " + authorName + " 发了一篇文章 " + articleName);
    }
}

Test category

public class Main {

    public static void main(String[] args) {
        WeChatServer weChatServer = new WeChatServer("Java识堂");
        WeChatClient user1 = new WeChatClient("张三");
        WeChatClient user2 = new WeChatClient("李四");
        weChatServer.registerObserver(user1);
        weChatServer.registerObserver(user2);
        weChatServer.publishArticle("《五分钟学会观察者模式》");
    }
}

Output

张三: Java识堂 发了一篇文章 《五分钟学会观察者模式》
李四: Java识堂 发了一篇文章 《五分钟学会观察者模式》

Application observer pattern

JDK provides the observer mode interface

Java has observer mode support in java.util package, which defines two interfaces

Abstract observer

public interface Observer {
    void update(Observable o, Object arg);
}

Abstract theme

public class Observable {
    private boolean changed = false;
    private Vector<Observer> obs;

    public Observable() {
        obs = new Vector<>();
    }

    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

    public void notifyObservers() {
        notifyObservers(null);
    }

    public void notifyObservers(Object arg) {
	
        Object[] arrLocal;

        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    protected synchronized void setChanged() {
        changed = true;
    }

    protected synchronized void clearChanged() {
        changed = false;
    }

    public synchronized boolean hasChanged() {
        return changed;
    }

    public synchronized int countObservers() {
        return obs.size();
    }
}

And we are very similar to the previously defined Kazakhstan, but more a change of the switching field, and to ensure the security thread

Let's rewrite the previous example about the definition of the event object

@Data
@AllArgsConstructor
public class NewArticleEvent {

    private String authorName;
    private String articleName;
}
public class WeChatServer extends Observable {

    private String authorName;
    private String articleName;

    public WeChatServer(String authorName) {
        this.authorName = authorName;
    }

    public void publishArticle(String articleName) {
        setChanged();
        this.articleName = articleName;
        notifyObservers(new NewArticleEvent(authorName, articleName));
    }
}
public class WeChatClient implements Observer {

    private String username;

    public WeChatClient(String username) {
        this.username = username;
    }

    @Override
    public void update(Observable o, Object arg) {
        NewArticleEvent event = (NewArticleEvent) arg;
        System.out.println(username + ": " + event.getAuthorName() + " 发了一篇文章 " + event.getAuthorName());
    }
}
public class Main {

    public static void main(String[] args) {
        WeChatServer weChatServer = new WeChatServer("Java识堂");
        WeChatClient user1 = new WeChatClient("张三");
        WeChatClient user2 = new WeChatClient("李四");
        weChatServer.addObserver(user1);
        weChatServer.addObserver(user2);
        weChatServer.publishArticle("《五分钟学会观察者模式》");
    }
}

Output Same as above

Custom event in the spring

Spring observer mode to achieve with the event listener, the event listener is relatively simple to achieve in the spring, or to transform what the above example

Event Type classes need to inherit ApplicationEvent

@Data
public class NewArticleEvent extends ApplicationEvent {

    private String authorName;
    private String articleName;

    public NewArticleEvent(Object source, String authorName, String articleName) {
        super(source);
        this.authorName = authorName;
        this.articleName = articleName;
    }

}

We can be realized by implementing event listeners ApplicationListener interface or use @EventListener comment

@Component
public class NewArticleEventListener implements ApplicationListener<NewArticleEvent> {

    @Override
    public void onApplicationEvent(NewArticleEvent event) {
        System.out.println(event.getAuthorName() + " 发了一篇文章 " + event.getArticleName());
    }
}
@Component
public class MyEventListener {

    @EventListener
    public void newArticleEventListener(NewArticleEvent event) {
        System.out.println(event.getAuthorName() + " 发了一篇文章 " + event.getArticleName());
    }
}

The above example was made viewers in two ways, the following test class start writing. The above classes in the package Ha com.javashitang.part6

@Configuration
@ComponentScan("com.javashitang.part6")
public class AppConfig {
}
public class Main {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		context.publishEvent(new NewArticleEvent(context, "Jva识堂", "《五分钟学会观察者模式》"));
		context.close();
	}
}

At this point you can see the console output

Jva识堂 发了一篇文章 《五分钟学会观察者模式》
Jva识堂 发了一篇文章 《五分钟学会观察者模式》

Well, now you'll have a custom event in the spring. Achieve spring in the observer pattern may complicated, but the basic idea is mentioned above.

  • Spring is ApplicationEvent event interface
  • Spring is ApplicationListener event listener interface, all of the listeners have to implement the interface
  • Spring is ApplicationEventPublisher event publishing interface, ApplicationContext implements this interface

spring offers some ApplicationEvent implementation class for us

  • ContextStartedEvent: ApplicationContext container issued during initialization of the event type
  • ContextClosedEvent: ApplicationContext container published in going to shut down the event type
  • ContextRefreshedEvent: ApplicationContext container published in the initialization or refresh when the event type

If you want to know a good application of spring events in the project definition. You can see my previous article, we look at how to use annotations + spring events to implement the strategy pattern

Project if else too, how to reconstruct?

User - defined event in spring-cloud-eureka in

We all know that eureka is a registry, save the service name -> ip address specific relationship, it is
ConcurrentHashMap to save the mapping relationship. Since it is certainly related to the registration center to register and cancel services, eureka in the register (registration), cancel (cancel), when renew (renewal) happens, will publish an event, as shown in the following code

InstanceRegistry.java

private void handleRegistration(InstanceInfo info, int leaseDuration,
		boolean isReplication) {
	log("register " + info.getAppName() + ", vip " + info.getVIPAddress()
			+ ", leaseDuration " + leaseDuration + ", isReplication "
			+ isReplication);
	publishEvent(new EurekaInstanceRegisteredEvent(this, info, leaseDuration,
			isReplication));
}

If you are more interested in information services, such as data persistence want, you can listen to these events, scalability is not particularly good?

Reference blog

[1] https://juejin.im/post/5bcf53f351882577e5120b99#heading-8
the Spring the Boot whole process, there is an event part
[2] https://www.jianshu.com/p/83693d3d0a65
[3] HTTPS: // Blog .lqdev.cn / 2018/11/06 / springboot / chapter-thirty-two /

Published 385 original articles · won praise 1471 · Views 900,000 +

Guess you like

Origin blog.csdn.net/zzti_erlie/article/details/104736416