Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

An example Analysis of the Observer pattern of Java Design pattern

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article will explain in detail the example analysis of the observer pattern of the Java design pattern. The editor thinks it is very practical, so I share it with you for reference. I hope you can get something after reading this article.

Introduction

Observer pattern (Observer Pattern): defines an one-to-many dependency between objects, so that whenever the state of an object changes, its dependent objects are notified and updated automatically. Observer mode is a kind of object behavior model.

Aliases for the observer pattern include publish-subscribe (Publish/Subscribe) mode, model-view (Model/View) mode, source-listener (Source/Listener) mode, or subordinate (Dependents) mode.

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

It is generally many-to-one dependence, that is, one observer, and multiple observers.

Once the official account is updated, all fans who subscribe to its official account will receive the update push.

Role

Subject (goal): a goal, also known as a topic, refers to the object being observed. A set of observers is defined in the target, which can be observed by any number of observers, it provides a series of methods to add and delete observer objects, and it defines the notification method notify (). The target class can be an interface, an abstract class, or a concrete class.

ConcreteSubject (specific goal): a specific goal is a subclass of the target class, which usually contains data that changes frequently and notifies its observers when its state changes; it also implements abstract business logic methods, if any, defined in the target class. If you do not need to extend the target class, the specific target class can be omitted.

Observer (observer): the observer will react to the change of the observation object. The observer is generally defined as an interface, which declares the method update () to update the data, so it is also called the abstract observer.

ConcreteObserver (concrete observer): maintains a reference to a specific target object in the concrete observer, which stores the relevant states of the specific observer, which need to be consistent with the state of the specific target; it implements the update () method defined in the abstract observer Observer. Usually when implementing, you can add yourself to the collection of the target class by calling the attach () method of the specific target class or remove yourself from the collection of the target class by the detach () method.

Principle class diagram

The case of Subscription account of Wechat

First you need a subscriber interface (viewer), which has a receive method to receive official account push notifications

/ / subscriber-Observer public interface Subscriber {/ / receive the method public void receive () of the publisher to publish the message;}

Then there is a Wechat client (concrete observer) that implements the receive method

/ / the business logic public class WeChatSub implements Subscriber {/ / the name of the current subscriber private String subName; WeChatSub (String subName) {this.subName=subName } @ Override public void receive (String publisher, String passageName) {/ / specific business logic operation System.out.println when receiving a push message (String.format ("user [% s], Subscription account push received by [% s]," + "push article:% s", subName,publisher,passageName));}}

Publisher class (target, observed object), which maintains a list of subscribers and implements functions such as subscribing, unsubscribing, notifying all subscribers, etc.

/ / publisher-the observed object Subjectpublic class Publisher {/ / stores all observers that need to be notified static private List subscribers=new ArrayList (); / / record the status of whether it is published. Default false static private Boolean pubStatus=false; protected void subscribe (Subscriber subscriber) {this.subscribers.add (subscriber) } protected void unsubscribe (Subscriber subscriber) {if (this.subscribers.contains (subscriber)) {this.subscribers.remove (subscriber);}} protected void notifySubscribers (String publisher, String articleName) {if (this.pubStatus = = false) {return;} for (Subscriber subscriber: this.subscribers) {subscriber.receive (publisher, articleName) } this.clearPubStatus ();} protected void setPubStatus () {this.pubStatus = true;} protected void clearPubStatus () {this.pubStatus = false;}}

Wechat official account class (specific target), which provides a publishArticles method for publishing and pushing, and calls the parent class's method to notify all subscribers when the article is published

Public class WeChatPublisher extends Publisher {private String name; public WeChatPublisher (String name) {this.name = name;} public void publishArticles (String articleName, String content) {System.out.println ("\ nofficial Wechat account posted a push with the title", this.name, articleName, content); setPubStatus (); notifySubscribers (this.name, articleName);}}

Client test

/ / client public class Client {public static void main (String [] args) {/ / create a publisher WeChatPublisher dhy=new WeChatPublisher ("big hoax"); / / create a subscriber Subscriber sub1=new WeChatSub ("child"); Subscriber sub2=new WeChatSub ("little hoax"); Subscriber sub3=new WeChatSub ("big friend"); / / subscribe to the big hoax official account dhy.subscribe (sub1) Dhy.subscribe (sub2); dhy.subscribe (sub3); / / release push dhy.publishArticles ("Design pattern", "Observer pattern");}}

Summarize the advantages

The observer pattern can separate the presentation layer from the data logic layer, define a stable message update delivery mechanism, and abstract the update interface, so that a variety of different presentation layers can act as specific observers.

The observer pattern establishes an abstract coupling between the observation target and the observer. The observation target only needs to maintain a collection of abstract observers and does not need to know its specific observers. Because the observation target and the observer are not closely coupled, they can belong to different levels of abstraction.

Observer mode supports broadcast communication, and the observation target sends notifications to all registered observer objects, simplifying the difficulty of one-to-many system design.

The observer mode meets the requirements of the "opening and closing principle", adding new specific observers does not need to modify the original system code, and it is convenient to add new observation targets when there is no correlation between the specific observer and the observation target.

Shortcoming

If a target has many direct and indirect observers, it takes a lot of time to notify all the observers.

If there is a circular dependency between the observer and the observation target, the observation target will trigger a circular call between them, which may cause the system to crash.

The observer model has no corresponding mechanism to let the observer know how the observed object has changed, but only that the observed object has changed.

Applicable scenario

An abstract model has two aspects, one of which depends on the other, which is encapsulated in separate objects so that they can be changed and reused independently.

A change in one object will cause one or more other objects to change, without knowing exactly how many objects will change or who they are.

You need to create a trigger chain in the system, the behavior of An object will affect B object, and the behavior of B object will affect C object. You can use observer mode to create a chained trigger mechanism

Observer interface provided by JDK, a typical application of the observer pattern

The observer pattern plays an important role in the Java language. In the java.util package of JDK, the Observable class and the Observer interface are provided, which constitute JDK's support for the observer pattern.

The Observer interface is the observer, and there is only one update method, which is called when the observation target changes. The code is as follows:

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

The Observable class is the target class, with more concurrency and NPE considerations than the Publisher class in our example.

Public class Observable {private boolean changed = false; private Vector obs = new Vector (); public Observable () {} / / is used to register a new observer object into the vector public synchronized void addObserver (Observer var1) {if (var1 = = null) {throw new NullPointerException () } else {if (! this.obs.contains (var1)) {this.obs.addElement (var1);} / / to delete one of the observer objects in the vector public synchronized void deleteObserver (Observer var1) {this.obs.removeElement (var1);} public void notifyObservers () {this.notifyObservers ((Object) null) } / / Notification method, update () method public void notifyObservers (Object var1) {Object [] var2; synchronized (this) {if (! this.changed) {return;} var2 = this.obs.toArray (); this.clearChanged () } for (int var3 = var2.length-1; var3 > = 0;-- var3) {((Observer) var2 [var3]) .update (this, var1);}} / / is used to empty the vector, that is, to delete all observer objects in the vector public synchronized void deleteObservers () {this.obs.removeAllElements () } / / after the method is called, the value of an internal tag variable changed of type boolean is set to true, indicating that the state of the observed target object has changed protected synchronized void setChanged () {this.changed = true } / / set the value of the changed variable to false, indicating that the state of the object no longer changes or all observers have been notified, and their update () method protected synchronized void clearChanged () {this.changed = false;} / / returns whether the state of the object has changed public synchronized boolean hasChanged () {return this.changed } / / returns the number of observers in the vector public synchronized int countObservers () {return this.obs.size ();}}

We can use the Observable class and the Observer interface to reimplement the Wechat official account example.

Add a notification class WechatNotice for the delivery of push notifications

@ Data@AllArgsConstructorpublic class WechatNotice {private String publisher; private String articleName;}

Then rewrite WeChatClient and WeChatAccounts to implement the Observer interface of JDK and inherit the Observable class respectively

Public class WeChatClient implements Observer {private String username; public WeChatClient (String username) {this.username = username;} @ Override public void update (Observable o, Object arg) {/ / WeChatAccounts weChatAccounts = (WeChatAccounts) o; WechatNotice notice = (WechatNotice) arg System.out.println (String.format ("users receive a push from Wechat official account, the article is titled", username, notice.getPublisher (), notice.getArticleName ());}} public class WeChatAccounts extends Observable {private String name; public WeChatAccounts (String name) {this.name = name } public void publishArticles (String articleName, String content) {System.out.println (String.format ("\ nofficial account of Wechat posted a push with the title of", this.name, articleName, content); setChanged (); notifyObservers (new WechatNotice (this.name, articleName));}}

The difference between the test and the test code in the example is that the method is called

Public class Test {public static void main (String [] args) {WeChatAccounts accounts = new WeChatAccounts ("big hoax"); WeChatClient user1 = new WeChatClient ("Zhang San"); WeChatClient user2 = new WeChatClient ("Li Si"); WeChatClient user3 = new WeChatClient ("Wang Wu"); accounts.addObserver (user1); accounts.addObserver (user2); accounts.addObserver (user3) Accounts.publishArticles ("Design pattern | Observer pattern and typical applications", "content of Observer pattern..."); accounts.deleteObserver (user1); accounts.publishArticles ("Design pattern | Singleton pattern and typical Application", "content of Singleton pattern...."); Observer pattern in Guava EventBus}

EventBus in Guava encapsulates a friendly "production / consumption model" and implements snooping registration and event distribution in observer mode in a very simple way.

After using Guava EventBus, if you need to subscribe to a message, you don't need to implement any interfaces, you just need to annotate the listening method with @ Subscribe. EventBus provides register and unregister methods for registering and unregistering events. When EventBus calls the post method, events will be distributed to the registered object.

Reimplement the example using Guava

@ Data@AllArgsConstructorpublic class WechatNotice {private String publisher; private String articleName;} public class WeChatClient {private String username; public WeChatClient (String username) {this.username = username;} @ Subscribe public void listen (WechatNotice notice) {System.out.println ("user receives a push from Wechat official account, the article is titled", username, notice.getPublisher (), notice.getArticleName () }} public class WeChatAccounts {private String name; private EventBus eventBus; public WeChatAccounts (String name) {this.name = name; this.eventBus = new EventBus ();} public void publishArticles (String articleName, String content) {System.out.println (String.format ("\ nofficial account of Wechat released a push entitled", this.name, articleName, content)) / / the post method will pass the dispatched message to all subscribers and call the subscriber's listening method this.eventBus.post (new WechatNotice (this.name, articleName));} public void register (WeChatClient weChatClient) {this.eventBus.register (weChatClient);} public void unregister (WeChatClient weChatClient) {this.eventBus.unregister (weChatClient);}}

test

Public class Test {public static void main (String [] args) {WeChatAccounts accounts = new WeChatAccounts ("small swirl front"); WeChatClient user1 = new WeChatClient ("Zhang San"); WeChatClient user2 = new WeChatClient ("Li Si"); WeChatClient user3 = new WeChatClient ("Wang Wu"); accounts.register (user1); accounts.register (user2); accounts.register (user3) Accounts.publishArticles ("Design pattern | Observer pattern and typical applications", "content of Observer pattern..."); accounts.unregister (user1); accounts.publishArticles ("Design pattern | Singleton pattern and typical Application", "content of Singleton pattern....");} Observer pattern in Spring ApplicationContext event mechanism

The event mechanism of spring is extended from the event mechanism of java. Event handling in ApplicationContext is provided by ApplicationEvent class and ApplicationListener interface. If a Bean implements the ApplicationListener interface and has been published to the container, the Bean will be notified every time the ApplicationContext publishes an ApplicationEvent event

ApplicationContext: event source, where the publishEvent () method is used to trigger container events

ApplicationEvent: the event itself. Custom events need to inherit this class and can be used to pass data.

ApplicationListener: event listener interface. The business logic of the event is encapsulated in the listener.

@ Datapublic class WechatNotice extends ApplicationEvent {private String publisher; private String articleName; public WechatNotice (Object source, String publisher, String articleName) {super (source); this.publisher = publisher; this.articleName = articleName;}} public class WeChatClient implements ApplicationListener {private String username; public WeChatClient (String username) {this.username = username } @ Override public void onApplicationEvent (ApplicationEvent event) {if (event instanceof WechatNotice) {WechatNotice notice = (WechatNotice) event; System.out.println (String.format ("users receive a push from Wechat official account, the article is titled", username, notice.getPublisher (), notice.getArticleName ());}} public void setUsername (String username) {this.username = username }} public class WeChatAccounts implements ApplicationContextAware {private ApplicationContext ctx; private String name; public WeChatAccounts (String name) {this.name = name;} public void setName (String name) {this.name = name;} @ Override public void setApplicationContext (ApplicationContext applicationContext) throws BeansException {this.ctx = applicationContext } public void publishArticles (String articleName, String content) {System.out.println (String.format ("\ nofficial account of Wechat posted a push with the title of", this.name, articleName, content); ctx.publishEvent (new WechatNotice (this.name, this.name, articleName));}}

Create a spring.xml file in the resources directory and fill in the following

test

Public class Test {public static void main (String [] args) {ApplicationContext context = new ClassPathXmlApplicationContext ("spring.xml"); WeChatAccounts accounts = (WeChatAccounts) context.getBean ("WeChatAccounts"); accounts.setName ("big bluff"); accounts.setApplicationContext (context); accounts.publishArticles ("Design pattern | Observer pattern and typical applications", "content of Observer pattern");}}

In this example, the actual type of the ApplicationContext object is ClassPathXmlApplicationContext, and the main code related to the publishEvent method is as follows:

Private ApplicationEventMulticaster applicationEventMulticaster;public void publishEvent (ApplicationEvent event) {this.getApplicationEventMulticaster () .multicastEvent (event); if (this.parent! = null) {this.parent.publishEvent (event);}} ApplicationEventMulticaster getApplicationEventMulticaster () throws IllegalStateException {return this.applicationEventMulticaster;} protected void initApplicationEventMulticaster () {ConfigurableListableBeanFactory beanFactory = this.getBeanFactory () If (beanFactory.containsLocalBean ("applicationEventMulticaster")) {this.applicationEventMulticaster = (ApplicationEventMulticaster) beanFactory.getBean ("applicationEventMulticaster", ApplicationEventMulticaster.class);} else {this.applicationEventMulticaster = new SimpleApplicationEventMulticaster (beanFactory); beanFactory.registerSingleton ("applicationEventMulticaster", this.applicationEventMulticaster);}}

The SimpleApplicationEventMulticaster is as follows. The multicastEvent method is mainly implemented by traversing the ApplicationListener (registration is implemented by AbstractApplicationEventMulticaster) and using the thread pool framework Executor to execute the onApplicationEvent method of ApplicationListener concurrently, which is essentially consistent with the example

Public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {private Executor taskExecutor; public void multicastEvent (final ApplicationEvent event) {Iterator var2 = this.getApplicationListeners (event) .iterator (); while (var2.hasNext ()) {final ApplicationListener listener = (ApplicationListener) var2.next (); Executor executor = this.getTaskExecutor () If (executor! = null) {executor.execute (new Runnable () {public void run () {listener.onApplicationEvent (event);}});} else {listener.onApplicationEvent (event) This is the end of the article on "sample Analysis of the Observer pattern of Java Design patterns". I hope the above content can be helpful to you so that you can learn more knowledge. if you think the article is good, please share it for more people to see.

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.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report