Observer mode of 23 design modes
reference material
- Java design patterns: comprehensive analysis of 23 design patterns (super detailed)
- Han Shunping's Java design pattern (illustration + framework source code analysis)
- Qin Xiaobo's Zen of design pattern
Please correct any mistakes and omissions below
1, Introduction
definition
It refers to the one to many dependency between multiple objects. When the state of an object changes, all objects that depend on it will be notified and updated automatically. (all observers will be notified when the content of the observed changes)
characteristic
- The observer model is a behavioral model
General class diagram
Important roles of observer mode:
-
Subject
Observer role
It provides a collection for saving observer objects, which can dynamically add and delete observers. Used to manage and inform observers.
-
ConcreteSubject
Specific observer role
Define your own business logic and implement the abstract methods in the abstract observed. When the internal state of the specific observed changes, it will notify all registered observer objects.
-
Observer
Abstract observer role
It is an abstract class or interface that contains an abstract method of update, which is called when the message from the observer is received.
-
ConcreteObserver
Specific observer role
Implement the abstract methods defined in the abstract observer, and each observer has its own processing logic.
advantage
- It reduces the coupling relationship between the observed and the observer, which is an abstract coupling relationship. In this design, it is very easy to expand whether the observer or the observed is added.
- A trigger mechanism is established between the observed and the observer. The observed sets the trigger conditions and notifies all observers once triggered.
shortcoming
-
The dependency between the observed and the observer has not been completely removed, and there may be circular references, that is, the observer may also be the observed.
-
When there are many observers, the notification of the press conference takes a lot of time, which affects the efficiency of the program.
Application scenario
- There is a one to many relationship between objects. The change of the state of one object will affect other objects.
- When an abstract model has two aspects, one of which depends on the other, they can be encapsulated in independent objects so that they can be changed and reused independently.
- Cross system message exchange scenarios, such as the processing mechanism of message queue.
2, Observer mode
Requirements:
Now there is a stock. Investors can set the reminder when the stock rises. Use observer mode to simulate this function.
Abstract Observer:
package observer.standard; import java.util.ArrayList; import java.util.List; public abstract class Subject { // Define a collection of observers protected List<Observer> observers = new ArrayList<>(); // Add an observer public void add(Observer observer) { observers.add(observer); } // Delete an observer public void remove(Observer observer) { observers.remove(observer); } // Notify all observers public abstract void notifyObservers(); }
Specific observers:
package observer.standard; public class Stock extends Subject { private double money = 1.0; // Logic of custom notification method public void setMoney(double money) { // Only when the current stock price rises will all observers be notified if (money > this.money) { this.money = money; notifyObservers(); } this.money = money; } // Implementation notification method @Override public void notifyObservers() { for (Observer observer : observers) { observer.update(money); } } }
Abstract Observer:
package observer.standard; public interface Observer { // Update method public void update(double money); }
Specific observers:
package observer.standard; public class Investor implements Observer { private String name; public Investor(String name) { this.name = name; } // Implementation update method @Override public void update(double money) { System.out.println(name + "The stock you are concerned about has risen, and the current price is per share" + money + "element"); } }
Client:
package observer.standard; public class Client { public static void main(String[] args) { // Simulate three users subscribing to the rise reminder of the same stock Observer user1 = new Investor("Space"); Observer user2 = new Investor("Spencer"); Observer user3 = new Investor("Alice"); // Add observer Stock stock = new Stock(); stock.add(user1); stock.add(user2); stock.add(user3); // The observer updates the status and notifies all observers stock.setMoney(1.12); System.out.println("==================="); stock.setMoney(1.2); System.out.println("==================="); // Since the share price did not rise, the observer was not informed stock.setMoney(1.1); /** * Output result: * Space The stock you are concerned about has risen. The current price is 1.12 yuan per share * Spencer The stock you are concerned about has risen. The current price is 1.12 yuan per share * Alice The stock you are concerned about has risen. The current price is 1.12 yuan per share * =================== * Space The stock you are concerned about has risen. The current price is 1.2 yuan per share * Spencer The stock you are concerned about has risen. The current price is 1.2 yuan per share * Alice The stock you are concerned about has risen. The current price is 1.2 yuan per share * =================== */ } }
When a new investor wants to set the rise of the stock, he just needs to add it to the observer set.
When there is a new stock, it is necessary to add a new specific subject class (observed). When the new stock changes, all observers will be notified, but in fact, we only want the shareholders who pay attention to the stock to receive the message. At this time, we can use double assignment to specify the type of object (the type of observed) and then choose whether to execute the update method. Fortunately, JDK has implemented the observer function with double dispatch for us.
Built in observer mode in JDK
Specific observers:
package observer.jdk; import java.util.Observable; public class StockA extends Observable { private double money = 1.0; // Logic of custom notification method public void setMoney(double money) { // Only when the current stock price rises will all observers be notified if (money > this.money) { // Update share price this.money = money; // The content of setting the observed has been changed this.setChanged(); // Notify all observers of updates this.notifyObservers(money); } // Update share price this.money = money; } }
package observer.jdk; import java.util.Observable; public class StockB extends Observable { private double money = 1.0; // Logic of custom notification method public void setMoney(double money) { // Only when the current stock price rises will all observers be notified if (money > this.money) { // Update share price this.money = money; // The content of setting the observed has been changed this.setChanged(); // Notify all observers of updates this.notifyObservers(money); } // Update share price this.money = money; } }
Observer:
package observer.jdk; import java.util.Observable; import java.util.Observer; public class Investor implements Observer { private String name; public Investor(String name) { this.name = name; } // Implementation update method @Overrideaaa public void update(Observable o, Object arg) { // Judge whether it is the (specific) observer who pays attention to the stock, and only observe the change of StockA if(o instanceof StockA){ System.out.println(name+"Stocks you focus on A It's up. Now the price is per share"+arg+"element"); } } }
Client:
package observer.jdk; public class Client { public static void main(String[] args) { // Simulate three users subscribing to the rise reminder of the same stock Investor user1 = new Investor("Space"); Investor user2 = new Investor("Spencer"); Investor user3 = new Investor("Alice"); // Add an observer for StockA StockA stockA = new StockA(); stockA.addObserver(user1); stockA.addObserver(user2); stockA.addObserver(user3); // Add an observer for StockB StockB stockB = new StockB(); stockB.addObserver(user1); stockB.addObserver(user2); stockB.addObserver(user3); // Update StockA's share price System.out.println("========StockA==========="); stockA.setMoney(1.12); System.out.println("==================="); stockA.setMoney(1.2); // Update the stock price of StockB. No matter the change of StockB, StockB has no output System.out.println("========StockB==========="); stockB.setMoney(1.12); System.out.println("==================="); // The observer updates the status and notifies all observers stockB.setMoney(1.2); /** * Output result: * ========StockA=========== * Alice Stock A you are concerned about has risen. The current price is 1.12 yuan per share * Spencer Stock A you are concerned about has risen. The current price is 1.12 yuan per share * Space Stock A you are concerned about has risen. The current price is 1.12 yuan per share * =================== * Alice The stock A you are concerned about has risen. The current price is 1.2 yuan per share * Spencer The stock A you are concerned about has risen. The current price is 1.2 yuan per share * Space The stock A you are concerned about has risen. The current price is 1.2 yuan per share * ========StockB=========== * =================== */ } }
3, Summary
Observer mode can establish a trigger mechanism for one to many dependencies. When the observed triggers the mechanism, all observers will be notified to update. And through the built-in Java util. Observable implementation class and Java util. Observer interface can easily implement observer mode and process specific observers.