Defines a one-to-many dependency of an object, and when the state of an object changes, all objects that depend on it are notified and automatically updated.
the role of the Observer pattern
1. Abstract Theme Role (Subject): All references to the Observer object are saved in a collection, and each abstract theme role can have any number of observers. Abstract topics provide an interface that can add and remove observer roles. It is generally implemented with an abstract class and interface.
2. specific thematic role (ConcreteSubject): Notify all registered observers when changes are made to the internal state of a specific subject. A specific theme role is typically implemented with a subclass.
3. Abstract Observer Role (Observer): Define an interface for all the tubes to erase, update yourself on the notification that gets the subject.
4. specific observer role (CONCRETEOBSERVER): This role implements the update interface required by the abstract observer role to reconcile the state of itself with the state of the topic. Typically implemented with a subclass. If desired, the specific observer role can maintain a reference to a specific topic role.
A simple example:
1 Abstract Viewer role (Observer):
publicinterface Observer{ publicvoidupdate(String str);}
2 Abstract Theme Role (Subject)
Public Abstract classsubject{Privatelist<observer> list =NewArraylist<> (); Public void Attach(Observer Observer) {LIST.ADD (Observer); } Public void Detach(Observer Observer) {LIST.REMOVE (Observer); } Public void notifyobservers(String str) {intLen = List.size (); for(intI=0; i<len;i++) {list.Get(i). Update (STR); } }}
3 Specific theme roles (ConcreteSubject)
publicclass ConcreteSubject extends Subject{ private String subjectState; publicgetState(){ return subjectState; } publicvoidsetState(String newState) { this.subjectState = newState; System.out.println("主题状态为: "+subjectState); this.notifyObservers(subjectState); }}
4 Specific observer roles (Concreteobserver)
publicclass ConcreteObserver implements Observer{ private String observerState; @Override publicvoidupdate(String state) { observerState = state; System.out.println("状态为: "+observerState); }}
- Test code:
new ConcreteSubject(); new ConcreteObserver(); subject.attach(observer); subject.setState("new State");
Output Result:
newnew State
push models and pull models
In the observer mode, it is divided into two ways: push model and pull model.
1. Push the model : The Subject object pushes the details of the topic to the viewer, regardless of whether the viewer needs it, the information that is pushed is usually all or part of the data for the subject object.
2. Pull model : Subject object When notifying the observer, only a small amount of information is passed. If the observer needs more specific information, the Observer takes the initiative to get to the subject object, which is equivalent to the observer pulling data from the subject object. In the general implementation of this model, the subject object itself is passed to the observer through the update () method, which can be obtained by this reference when the observer needs to obtain the data.
Modify the above code to change to a pull model case:
1 abstract observer role Observer2, usually passing the subject object as a parameter
publicinterface Observer2{ publicvoidupdate(Subject2 subject);}
2 Specific Observer roles
publicclass ConcreteObserver2 implements Observer2{ private String observerState; @Override publicvoidupdate(Subject2 subject) { observerState = ((ConcreteSubject2)subject).getState(); System.out.println("状态为: "+observerState); }}
3 Abstract Theme Roles
Public Abstract classsubject2{Privatelist<observer2> list =NewArraylist<> (); Public void Attach(Observer2 observer) {LIST.ADD (Observer); } Public void Detach(Observer2 observer) {LIST.REMOVE (Observer); } Public void notifyobservers() {intLen = List.size (); for(intI=0; i<len;i++) {list.Get(i). Update ( This); } }}
4 Specific Theme Roles
publicclass ConcreteSubject2 extends Subject2{ private String subjectState; publicgetState(){ return subjectState; } publicvoidsetState(String newState) { this.subjectState = newState; System.out.println("主题状态为: "+subjectState); this.notifyObservers(); }}
Test code:
new ConcreteSubject2(); new ConcreteObserver2(); subject.attach(observer); subject.setState("new State");
Output result: (same as previous case)
Two modes of comparison :
- The push model assumes that the subject object knows the data that the observer needs, whereas the pull model is a subject object that does not know what data the observer specifically needs and, without a means, simply transmits itself to the observer, allowing the observer to take the value on its own.
- Pushing a model may make it difficult to reuse the observer object because the Observer's update () method is a parameter that is defined as needed, and may not be able to take into account unused usage. This means that a new update () method may be available when a new situation arises, or simply a re-implementation of the observer, whereas the pull model does not cause this, since the parameters of the update () method under the pull model are the subject object itself, which is basically the largest collection of data that the subject object can deliver. Can basically adapt to the needs of various situations.
Pros and cons
Advantages:
1. Subject and observer are loosely coupled, respectively, and can be individually changed.
2. Subject when sending a broadcast notification, you do not need to specify a specific observer,observer to decide whether to subscribe to subject notifications.
Disadvantages:
1. Loose softness leads to a code relationship that is not obvious, and can sometimes be difficult to understand
2. If a subject is subscribed by a large number of observer, there may be an efficiency issue when broadcasting a notification.
Applicable Scenarios
1. Updates to an object state require other objects to be updated synchronously, and the number of other objects changes dynamically.
2. Objects only need to notify their own updates to other objects without needing to know the details of other objects.
Observer patterns in the JDK:
Java.util.EventListener
Javax.servlet.http.HttpSessionBindingListener
Javax.servlet.http.HttpSessionAttributeListener
Javax.faces.event.PhaseListener
Resources
1. "23 Design Patterns"
2. Design patterns in the "digital JDK"
3. The observer model of Java and patterns
Design mode: Observer Mode (OBSERVER)