I. What is the observer model?
The behavior of one object depends on the state of the other. In other words, when the state of the observed object (the target object) changes, it directly affects the behavior of the observed object.
There are several objects involved:
- The observer
- The observed
- Change of state
For example: high school evening study, there will always be a wave of naughty students, while the teacher is not in the classroom, playing poker, and then find someone to watch at the door, the teacher comes, quickly inform the inside playing poker students, students quickly put away their cards, into a careful state. Let’s analyze the roles here
- Observer: a student standing guard at the teacher
- Observed: Teacher
- Event: When the observed teacher came to the teacher, the observer sent a signal to the students playing poker inside, the teacher is coming, quickly put it away.
The Observer pattern, also known as Publish/Subscribe, defines a one-to-many dependency between objects so that whenever an object changes state, all dependent objects are notified and automatically updated. The UML structure diagram is as follows:
The relationship between the observed and the observer is generally one-to-many. One observed corresponds to multiple observers. When the state of an observed changes, the observed notifies the observer, and then the business logic can be processed within the observer.
The principle of the observer model
According to the on-line UML diagram, we know that the observed mainly has the following parts
- Abstract observed Subject: The observed changes and needs to be notified to the observer.
- Concrete observed ConcreteSubject: There is only one concrete observed concretely.
- Abstract Observer: Receives changes and performs logic accordingly.
- ConcreteObserver: Usually there are one or more concreteObservers.
- The client client
Let’s look at the code implementation:
- The abstract observed
package com.lxl.www.designPatterns.observerPattern.observer;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
/** ** observed */
public abstract class Subject {
/** * One observed for multiple observers */
List<Observer> observers = new ArrayList<Observer>();
/** * increases the observed */
public void addObserver(Observer observer) {
observers.add(observer);
}
/** * deletes the observed */
public void deleteObserver(Observer observer) {
observers.remove(observer);
}
/** * notifies the observed */
public void notifyObserver(a) {
for (Observer observer: observers) {
// Tell the observer to processobserver.update(); }}abstract void event(a);
}
Copy the code
- Specific observed
package com.lxl.www.designPatterns.observerPattern.observer;
/** * specific observer */
public class ConcreteSubject extends Subject{
/** ** what happened */
public void event(a) {
System.out.println("I am [observed] ---- An event has occurred, inform the observers.");
super.notifyObserver(); }}Copy the code
- Abstract observer
package com.lxl.www.designPatterns.observerPattern.observer;
/** ** observer */
public abstract class Observer {
abstract void update(a);
}
Copy the code
- Concrete observer
package com.lxl.www.designPatterns.observerPattern.observer;
public class ConcreteOberverA extends Observer{
@Override
void update(a) {
System.out.println("I'm observer A-- I've been notified, execute the relevant processing logic."); }}public class ConcreteOberverB extends Observer{
@Override
void update(a) {
System.out.println("I'm observer B-- I've been notified, execute the relevant processing logic."); }}Copy the code
- The client client
package com.lxl.www.designPatterns.observerPattern.observer;
public class Client {
public static void main(String[] args) {
// There is an observer
Subject subject = new ConcreteSubject();
// There are two observers
Observer observerA = new ConcreteOberverA();
Observer observerB = new ConcreteOberverB();
subject.addObserver(observerA);
subject.addObserver(observerB);
// The observed emits an event, notifying the observerssubject.event(); }}Copy the code
Running results:
I am [observed] —- An event has occurred, inform the observers
I’m observer A– I’ve been notified and I’m doing the relevant processing logic
The observer model case
We use wechat every day now, and also pay attention to many wechat public accounts. If a wechat public number for example, let’s think about how to use the observer mode to achieve. Now there is a wechat public account, and N wechat users follow the wechat public account. When the wechat public account releases a message, all the wechat users who follow the wechat public account will be notified.
Analysis:
- Observed: Wechat official account. There is a collection of wechat users who follow me.
- Specific observed: my wechat official account
- Observer: Wechat user
- Specific observers: wechat users A, B, C, etc. who follow the wechat public account
- Wechat official account client: Send messages on the client
Here’s the source code:
- The observed
package com.lxl.www.designPatterns.observerPattern.weChat;
import java.util.ArrayList;
import java.util.List;
public abstract class WeChatPublicAccount {
List<WeChatObserver> weChatObservers = new ArrayList<WeChatObserver>();
/** * Add wechat user *@param weChatUser
*/
public void addWeChatObserver(WeChatObserver weChatUser) {
System.out.println("Add wechat observer" + weChatUser.getName() + "");
weChatObservers.add(weChatUser);
}
/** * Delete wechat user *@param weChatUser
*/
public void delWeChatObserver(WeChatObserver weChatUser) {
System.out.println("Delete wechat observer" + weChatUser.getName() + "");
weChatObservers.remove(weChatUser);
}
public void notifyWeChatObserver(a) {
for(WeChatObserver weChatObserver: weChatObservers) {
System.out.println("To the observer" + weChatObserver.getName() + "Send message"); weChatObserver.receive(); }}public abstract void writeArticle(a);
public abstract void promotions(a);
}
Copy the code
- Specific observed: my wechat official account
package com.lxl.www.designPatterns.observerPattern.weChat;
/** * My wechat official account */
public class MyWeChatPublicAccount extends WeChatPublicAccount{
@Override
public void writeArticle(a) {
System.out.println("Wrote an article to inform all my wechat followers.");
super.notifyWeChatObserver();
}
@Override
public void promotions(a) {
System.out.println("Launch a promotion to inform all wechat users who follow me.");
super.notifyWeChatObserver(); }}Copy the code
- Observer: Wechat user
package com.lxl.www.designPatterns.observerPattern.weChat;
public abstract class WeChatObserver {
protected String name;
/** * Receive message notification *@return* /
public abstract void receive(a) ;
public String getName(a) {
return name;
}
public void setName(String name) {
this.name = name; }}Copy the code
- Specific observers: wechat users A, B, C, etc. who follow the wechat public account
package com.lxl.www.designPatterns.observerPattern.weChat;
public class WeChatObserverZhangsan extends WeChatObserver{
public WeChatObserverZhangsan(a) {
super.name = "zhangSan";
}
/** * Receive message notification *@return* /
public void receive(a) {
System.out.println("Zhangsan has received a message"); }}package com.lxl.www.designPatterns.observerPattern.weChat;
public class WeChatObserverLisi extends WeChatObserver{
public WeChatObserverLisi(a) {
super.name = "lisi";
}
/** * Receive message notification *@return* /
public void receive(a) {
System.out.println("Lisi got the message."); }}Copy the code
- Wechat public account client
package com.lxl.www.designPatterns.observerPattern.weChat;
public class Client {
public static void main(String[] args) {
// Observed
WeChatPublicAccount publicAccount = new MyWeChatPublicAccount();
/ / observer
WeChatObserver observerZhangsan = new WeChatObserverZhangsan();
WeChatObserver observerLisi = new WeChatObserverLisi();
publicAccount.addWeChatObserver(observerZhangsan);
publicAccount.addWeChatObserver(observerLisi);
System.out.println("");
System.out.println();
// Write an article and broadcast it to everyone
publicAccount.writeArticle();
System.out.println("");
System.out.println();
// Observer Lisi unfollows
publicAccount.delWeChatObserver(observerLisi);
System.out.println("");
System.out.println();
// There is a promotion broadcast to everyonepublicAccount.promotions(); }}Copy the code
Running results:
ZhangSan added lisi to add wechat observer
Wrote an article to inform all my wechat followers
Send a message to The observer zhangSan. ZhangSan receives a message. Send a message to the observer LisI
Delete wechat observer Lisi
Launch a promotional activity, inform all my wechat users who follow me to send a message to the observer zhangSan zhangSan received the message
We can see that, zhang SAN and Li Si are concerned, then they can receive the message, Li Si cancelled the attention, can not receive the following message.
4. Observer mode expansion
In Java, the Observer pattern is defined through the java.util.Observable class and the java.util.Observer interface, and instances of the Observer pattern can be written by implementing their subclasses.
An Observable is an abstract target class. It has a Vector (or List) that holds all Observable objects to be notified of. Here are its three most important methods. A) void addObserver(Observer O) method: used to add a new Observer object to the vector. B) void notifyObservers(Object arg) method: Call update() on all observer objects in the vector to notify them of data changes. Observers who join the vector later are usually notified first. C) void setChange() : Sets an internal Boolean flag indicating that the target object has changed. When it is true, notifyObservers() notifyObservers. The Observer interface is an abstract Observer. It monitors the changes of the target Object. When the target Object changes, the Observer is notified and calls the void Update (Observable o,Object ARG) method to do the corresponding work
Let’s transform the scene of wechat public account broadcasting wechat messages
- Define a public account that inherits from the Observable abstract class
package com.lxl.www.designPatterns.observerPattern.jdkObserver;
import com.lxl.www.designPatterns.observerPattern.weChat.WeChatPublicAccount;
import java.util.Observable;
/** * The observed * my wechat official number */
public class MyWeChatPublicAccount extends Observable {
public void writeArticle(a) {
System.out.println("Wrote an article to inform all my wechat followers.");
super.setChanged();
super.notifyObservers();
}
public void promotions(a) {
System.out.println("Launch a promotion to inform all wechat users who follow me.");
super.setChanged();
super.notifyObservers(); }}Copy the code
- Define the Observer and implement the Observer interface
package com.lxl.www.designPatterns.observerPattern.jdkObserver;
import com.lxl.www.designPatterns.observerPattern.weChat.WeChatObserver;
import java.util.Observable;
import java.util.Observer;
public class WeChatObserverZhangsan implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("Zhangsan received a message sent from Tom"); }}Copy the code
package com.lxl.www.designPatterns.observerPattern.jdkObserver;
import com.lxl.www.designPatterns.observerPattern.weChat.WeChatObserver;
import java.util.Observable;
import java.util.Observer;
public class WeChatObserverLisi implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("Lisi received the message sent."); }}Copy the code
- Define a client that simulates relaxation messages
package com.lxl.www.designPatterns.observerPattern.jdkObserver;
import java.util.Observable;
import java.util.Observer;
public class Client {
public static void main(String[] args) {
// Observed
MyWeChatPublicAccount observable = new MyWeChatPublicAccount();
/ / observer
Observer observerZhangsan = new WeChatObserverZhangsan();
Observer observerLisi = new WeChatObserverLisi();
observable.addObserver(observerZhangsan);
observable.addObserver(observerLisi);
System.out.println("");
System.out.println();
// Write an article and broadcast it to everyone
observable.writeArticle();
System.out.println("");
System.out.println();
// Observer Lisi unfollows
observable.deleteObserver(observerLisi);
System.out.println("");
System.out.println();
// There is a promotion broadcast to everyoneobservable.promotions(); }}Copy the code
Running results:
I wrote an article to inform all my wechat users lisi received a message sent to me and Zhangsan received a message sent to me to launch a promotion. I notified all my wechat users zhangsan received a message sent to me
5. The usage scenario of observer mode
In a software system, when the behavior of one party depends on the change of the behavior of the other party, the observer mode can be used to loosely coupling the two parties, so that the change of one party can be notified to the object of the other party, so that the object of the other party can respond to it.
The above analysis and application examples show that the observer model is suitable for the following situations.
- Objects have a one-to-many relationship. Changes in the state of one object affect other objects.
- When an abstract model has two aspects, one of which depends on the other, the two can be encapsulated in separate objects so that they can be changed and reused independently.
- To realize functions similar to the broadcast mechanism, it is not necessary to know the specific receiver, but only to distribute the broadcast, and the interested objects in the system will automatically receive the broadcast.
- Multiple levels of nesting are used to form a chain trigger mechanism that allows events to be notified across domains (across both observer types).
Advantages and disadvantages of the observer model
advantages
The observer and the observed are abstractly coupled to establish a trigger mechanism
disadvantages
If an observed object has a lot of direct and indirect observers, it would take a lot of time to notify all of them and if there is a cyclic dependency between the observer and the observed object, it could cause the system to crash and there is no mechanism for the observer to know how the observed object is changing, right
Extensions – Publish, subscribe and observer patterns
Mq, which is often used in projects, is a way of publishing subscriptions. Is publishing subscriptions an observer model? Publishing and subscribing actually comes from the observer model, but it’s different.
The observer mode is only loosely coupled.
As shown above, in Observer mode, the instance object where the changed() method is located is the Subject, or Observable. It only needs to maintain a collection of observers that implement the same interface. All the Subject needs to know is, Notifying the Observer of which unified method needs to be invoked
The Observer pattern is somewhat similar to what we normally use mq, right? Publish and subscribe. Refer to this article in detail: zhuanlan.zhihu.com/p/51357583
Publish and subscribe model
Many people think that Publisher in the subscription mode is the Subject in the Observer mode and Subscriber is the Observer. When Publisher changes, take the initiative to inform Subscriber.
It’s not.
In the publish-subscribe model, the publisher does not directly notify the subscriber, in other words, the publisher and the subscriber do not know each other.
Strangers? How do they communicate?
The answer is through a third party, a Broker, in the message queue.
The publisher simply tells the Broker that the topic I want to send is AAA;
The subscriber simply tells the Broker that I want to subscribe to messages whose topic is AAA;
Thus, when the Broker receives a message from a publisher whose topic is AAA, it pushes the message to subscribers whose topic is AAA. Of course, there is also the possibility that the subscribers themselves come to pull, see the concrete implementation.
In other words, publishers and subscribers are not loosely coupled, but completely decoupled in a publish-subscribe model.
Here’s a picture of the difference between the two modes:
conclusion
On the face of it:
- In observer mode, there are only two roles – observer + observed
- In the publish-subscribe model, there are not only publishers and subscribers, but also a Broker that is often overlooked
To go deeper:
- The observer and the observed are loosely coupled
- Publishers and subscribers, there is no coupling at all
From the perspective of use:
- Observer mode, mostly used within a single application
- The publish-subscribe pattern is more of a cross-application pattern, such as messaging middleware