Design Pattern-Observer Pattern
Definition:
The Observer mode is also known as the Publish/Subscribe mode. GOF defines the observer mode as follows: defines a one-to-many dependency between objects. When the State of an object changes, all objects dependent on it are notified and automatically updated.
Components of the observer mode:
1) Abstract target role (Subject): The target role knows its observer. Multiple observers can observe the same target. It also provides interfaces for registering and deleting observer objects. The target role is often implemented by abstract classes or interfaces.
2) Abstract Observer role (Observer): defines an update interface for objects that need to be notified when the target changes. Abstract observer roles are mainly implemented by abstract classes or interfaces.
3) a specific target role (Concrete Subject): stores the relevant status into each Concrete Observer object. When its status changes, a notification is sent to its various observers.
4) A specific Observer role (Concrete Observer): stores the relevant status, which should be consistent with the target status. The Observer update interface is implemented to make its status consistent with that of the target. This role can also maintain a reference pointing to the Concrete Subject object.
The class graph structure of the observer mode:
Source code:
Abstract topic categories:
Public abstract class Subject {/*** is used to save the registered observer object */private List
List = new ArrayList
();/*** Register the observer object * @ param Observer observer object */public void attach (observer Observer) {list. add (observer); System. out. println (Attached an observer);}/*** Delete the observer object * @ param Observer observer object */public void detach (observer) {list. remove (observer);}/*** notify all registered Observer objects */public void nodifyObservers (String newState) {for (observer: list) {observer. update (newState );}}}
Specific topic categories:
Public class ConcreteSubject extends Subject {private String state; public String getState () {return state;} public void change (String newState) {state = newState; System. out. println (the topic status is + state); // The status changes and each observer is notified of this. nodifyObservers (state );}}
Abstract observer class:
Public interface Observer {/*** update interface * @ param state update status */public void update (String state );}
Specific observer class:
Public class ConcreteObserver implements Observer {// private String observerState of the Observer; @ Override public void update (String state) {/*** update the Observer state, make it consistent with the target status */observerState = state; System. out. println (Status: + observerState );}}
Test class:
Public class Client {public static void main (String [] args) {// create a topic object ConcreteSubject subject = new ConcreteSubject (); // create the Observer object observer Observer = new ConcreteObserver (); // register the observer object to the topic object subject. attach (observer); // change the status of the topic object subject. change (new state );}}
Output result:
At runtime, an instance of a specific topic class and an observer object are created. Then, it calls the attach () method of the topic object and registers the object with the topic object, that is, it adds it to the aggregation of the topic object.
At this time, the change () method of the topic is called to change the internal state of the topic object. When the status of a topic object changes, the notifyObservers () method of the super class is called to notify all registered observer objects.
Push model and pull model:
In the observer mode, there are two modes: Push model and pull model.
Push model: the topic object pushes the detailed information of the topic to the observer, regardless of whether the observer needs it or not. The pushed information is usually all or part of the data of the topic object.
Pull model: When a topic object notifies the observer, it only transmits a small amount of information. If the observer needs more specific information, the observer takes the initiative to get it from the topic object, which is equivalent to pulling data from the topic object. In general, the implementation of this model will pass the topic object itself to the observer through the update () method, so that the observer can obtain the data through this reference when it needs to obtain the data.
According to the above description, we found that the previous example is a typical PUSH model. Below is an example of the PULL model.
Abstract observer class for model pulling:
Public interface Observer {/*** update interface * @ param subject: Pass in the topic object to obtain the status of the corresponding topic object */public void update (Subject subject );}
Pull the specific observer class of the Model
Public class ConcreteObserver implements Observer {// private String observerState of the Observer; @ Override public void update (Subject subject) {/*** update the Observer State, make it consistent with the target status */observerState = (ConcreteSubject) subject ). getState (); System. out. println (Observer status: + observerState );}}
Abstract topic category of model pulling
The main change to the abstract topic class of the PULL model is the nodifyObservers () method. When the observer is notified cyclically, that is, when the observer's update () method is called cyclically, the input parameters are different.
Public abstract class Subject {/*** is used to save the registered observer object */private List
List = new ArrayList
();/*** Register the observer object * @ param Observer observer object */public void attach (observer Observer) {list. add (observer); System. out. println (Attached an observer);}/*** Delete the observer object * @ param Observer observer object */public void detach (observer) {list. remove (observer);}/*** notify all registered Observer objects */public void nodifyObservers () {for (observer: list) {observer. update (this );}}}
The specific topic category of the PULL model:
Compared with the push model, there is a slight change, that is, when calling the method to notify the observer, no parameters need to be input.
Public class ConcreteSubject extends Subject {private String state; public String getState () {return state;} public void change (String newState) {state = newState; System. out. println (the topic status is + state); // The status changes and each observer is notified of this. nodifyObservers ();}}
Comparison of the two models:
The push model assumes that the topic object knows the data that the observer needs, and the PULL model means that the topic object does not know the specific data that the observer needs. If there is no way, it simply passes itself to the observer, let the observer take the value as needed.
The push model may make it difficult to reuse the observer object because the update () method of the observer is a parameter defined as needed and may not take into account the usage that is not taken into account. This means that when a new situation occurs, a new update () method may be provided, or the observer may be re-implemented. Pulling the model won't cause this situation, because pulling the model, the parameter of the update () method is the topic object itself, which is basically the largest set of data that can be transferred by the topic object and can basically meet the needs of various situations.
Advantages of observer mode:
First, the observer mode establishes an abstract coupling between the observer and the observer. What the observer role knows is a specific observer list. Each specific observer conforms to an abstract observer interface. The observer does not know any specific observer, but only knows that they all have a common interface.
Since the observer and observer are not closely coupled, they can belong to different abstract layers. If the object is thrown together by both the observer and the observer, the object must span the abstract and concrete layers.
Second, the observer mode supports broadcast communication. The observer sends a notification to all registered observers.
Disadvantages of observer mode:
First, it takes a lot of time to notify all observers if they have many direct and indirect observers.
Second, if there is a circular dependency between the observer, the observer will trigger a circular call between them, resulting in system crash. Pay special attention to this when using the observer mode.
Third, if the notification to the observer is asynchronously delivered through another thread, the system must ensure that the delivery is carried out in the correct way.
Fourth, although the observer pattern can enable the observer to know that the observed object has changed at any time, the observer pattern does not have a mechanism to let the observer know how the observed object has changed.