Headfirst design pattern note-Observer Mode

Source: Internet
Author: User

Before implementing the observer mode, Let's first look at the needs of a weather forecast system. The weatherdata object is responsible for obtaining weather data (temperature, humidity, pressure) and then displaying it on the announcement board. There are many types of announcement boards.

Do not use the design mode:

Public class weatherdata {// when meteorological measurement updates data, this method calls public void measurementschanged () {// current temperature float temp = gettemperature (); // current humidity float humidity = gethumidity (); // current pressure Float Pressure = getpressure (); // update announcement board 1currentconditionsdisplay. update (temp, humidity, pressure); // announcement board 2currentconditionsdisplay2. update (temp, humidity, pressure); // announcement board 3currentconditionsdisplay3. update (temp, humidity, pressure );.......}}

The disadvantage of this method is obvious:

For specific implementation programming rather than interfaces, each announcement board must be added to the weatherdata class. If there is a change to the announcement board, you need to change the code.

The announcement board cannot be dynamically added/modified during running.

Destroys weatherdata encapsulation.

The update method of the announcement board can be abstracted into a public interface.

......

To solve these problems, it is convenient to use the observer mode.

The observer defines a one-to-multiple dependency between objects. When the State of an object (subject) changes, all dependent persons (observers) of the object will receive notifications and update automatically. After the observer is removed, no longer receive notifications.

Loose coupling: two objects can interact with each other, but they are not clear about the details of each other, minimizing the dependency between objects.

The observer mode loose coupling between the subject and the observer. When a new observer appears, the topic Code does not need to be modified. The observer registers in the topic. The topic does not care about the number of observers, but sends notifications to all objects that implement the observer interface.

Brief class diagram of observer mode:


The topic subjcet and the observer have a one-to-many relationship.

The three subject operations, registerobserver is used to register the observer object, removeobserver is used to remove the observer object, and policyobservers is used to notify all the observers.

The update method of the observer interface is used to receive notifications. In fact, it is used to call the policyobservers method of the subject implementation class.

Now let's take a look at the implementation of the Weather Forecast System in observer mode:

The weatherdata object must notify all the bulletin boards when data changes. According to the above concept, weatherdata must implement the subjcet interface and the bulletin board must implement the observer interface.

Subjcet interface:

public interface Subject {public void registerObserver(Observer o);public void removeObserver(Observer o);public void notifyObservers();}

Observer interface:

public interface Observer {public void update(float temp, float humidity, float pressure);}

Weatherdata:

Import Java. util. arraylist;/*** obtain meteorological data and notify the observer **/public class weatherdata implements subject {private arraylist <observer> observers; private float temperature; private float humidity; private float pressure; public weatherdata () {Observers = new arraylist <observer> () ;}@ overridepublic void registerobserver (Observer O) {observers. add (o) ;}@ overridepublic void removeobserver (Observer O) {int I = observers. indexof (o); if (I> 0) observers. remove (I) ;}@ overridepublic void policyobservers () {for (INT I = 0; I <observers. size (); I ++) {observer = observers. get (I); Observer. update (temperature, humidity, pressure) ;}} public void measurementschanged () {notifyobservers ();}/*** simulate meteorological data changes **/Public void setmeasurements (float temperature, float humidity, Float Pressure) {This. temperature = temperature; this. humidity = humidity; this. pressure = pressure; measurementschanged ();}}

One of the bulletin board currentconditionsdisplay:

/*** Announcement board, one of the observers **/public class currentconditionsdisplay implements observer, displayelement {private float temperature; private float humidity; private float pressure; // reference private subject weatherdata; Public currentconditionsdisplay (weatherdata) {This. weatherdata = weatherdata; weatherdata. registerobserver (this) ;}@ overridepublic void display () {system. out. println ("temperature =" + temperature + "; humidity =" + humidity + "; pressure =" + pressure) ;}@ overridepublic void Update (float temp, float humidity, float Pressure) {This. temperature = temp; this. humidity = humidity; this. pressure = pressure; display () ;}// remove the observer private void quit () {weatherdata. removeobserver (this );}}

The displayment interface is irrelevant and used to display data.

public interface DisplayElement {public void display();}

We can see that the weatherdata class implementing the subject interface maintains the arraylist of an observer interface to dynamically maintain the registered and canceled observer.

Once the weather data changes, call the measurementschanged method. The measurementschanged method calls notifyobservers. yyobservers actually traverses all the observers registered in the weatherdata class and then calls their update method. This is a "push" process. The observer does not need to manually retrieve data from the subject. This enables "when the status of an object (topic) changes, all dependent persons (observers) of the object will receive notifications and update automatically. After the observer is removed, no notification will be received ." Concept

Now call the test code:

public class WeatherStation {public static void main(String[] args) {WeatherData wData = new WeatherData();CurrentConditionsDisplay curDis = new CurrentConditionsDisplay(wData);wData.setMeasurements(80, 65, 30.4f);wData.setMeasurements(81, 61, 33.4f);wData.setMeasurements(82, 62, 31.4f);}}

Console output:

Temperature = 80.0; humidity = 65.0; pressure = 30.4
Temperature = 81.0; humidity = 61.0; pressure = 33.4
Temperature = 82.0; humidity = 62.0; pressure = 31.4

Java built-in observer Mode

In Java, the observable class and the observer interface have helped us implement the observer mode, and we can choose to push or pull.

The difference between pushing and pulling is whether the observer actively retrieves data from the topic. In the code, the observer uses the yyobservers method to determine whether to pass the parameter. If the parameter is passed, the observer does not pass the parameter, the updated data must be obtained by the observer calling the get method of the topic.

The comments section of the Code above shows the changes. Note that the changes are compared with the previous programs and the changes to the interfaces they implement!

Weatcherdata. Java

Import Java. util. hashmap; import Java. util. map; import Java. util. observable;/*** obtain meteorological data and notify the observer **/public class weatherdata extends observable {// implements subject {// Private arraylist <observer> observers; private float temperature; private float humidity; private Float Pressure; Public weatherdata () {// Observers = new arraylist <observer> () ;}// @ override // public void registerobserver (Observer O) {// observers. add (o); //} // @ override // public void removeobserver (Observer O) {// int I = observers. indexof (o); // if (I> 0) // observers. remove (I); //} // @ override // public void policyobservers () {// For (INT I = 0; I <observers. size (); I ++) {// observer = observers. get (I); // observer. update (temperature, humidity, pressure); //} // public void measurementschanged () {// policyobservers (); //} public void measurementschanged () {/* policyobservers is the built-in method of observable. before using it, you must call setchanged before the observer can receive the notification */setchanged (); // The temperature and other information are encapsulated in the map and passed to the observer Map <string, Object> map = new hashmap <string, Object> (); map. put ("temperature", temperature); map. put ("humidity", humidity); map. put ("pressure", pressure); notifyobservers (MAP);}/*** simulate meteorological data changes **/Public void setmeasurements (float temperature, float humidity, Float Pressure) {This. temperature = temperature; this. humidity = humidity; this. pressure = pressure; measurementschanged ();}}

Currentconditionsdisplay. Java

Import Java. util. map; import Java. util. observable;/*** announcement board, where one observer **/public class currentconditionsdisplay implements displayelement, Java. util. observer {// observer, displayelement {private float temperature; private float humidity; private Float Pressure; // reference of the topic // Private subject weatherdata; // reference of the observable object private observable observerable; // public currentconditionsdisplay (weatherdata) {// This. weatherdata = weatherdata; // weatherdata. registerobserver (this); //} public currentconditionsdisplay (observable) {This. observerable = observable; observerable. addobserver (this) ;}@ overridepublic void display () {system. out. println ("temperature =" + temperature + "; humidity =" + humidity + "; pressure =" + pressure);} // @ override // public void Update (float temp, float humidity, Float Pressure) {// This. temperature = temp; // This. humidity = humidity; // This. pressure = pressure; // display (); //} // use Java. util. observer update method @ overridepublic void Update (observable o, object Arg) {// checks whether the information is transmitted by the weatherdata topic if (O instanceof weatherdata) {// This is the pulling method // weatherdata = (weatherdata) O; // This. temperature = weatherdata. getxxxx // This is the push method Map <string, Object> map = (Map <string, Object>) ARG; this. temperature = (float) map. get ("temperature"); this. humidity = (float) map. get ("humidity"); this. pressure = (float) map. get ("pressure"); display ();}}}

The test class remains unchanged. Running result:

Temperature = 80.0; humidity = 65.0; pressure = 30.4
Temperature = 81.0; humidity = 61.0; pressure = 33.4
Temperature = 82.0; humidity = 62.0; pressure = 31.4

The built-in implementation in Java is much more convenient, but it also has disadvantages. For example, the observable is a class rather than the subjcet interface implemented as the first program, which reduces flexibility.

The observer mode is used in many places, such as listener.

For example, Android button listening

setOnClickListener(new OnClickListener(){

The control object is actually a "topic", and the onclicklistener class is an observer. rewriting its onclick method is equivalent to rewriting the update method. When the button is clicked, the registered observer, that is, the onclicklistener onclick method, is called.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.