观察者模式

观察者模式:定义了对象之间的一对多依赖,这样当一个对象改变状态是,它的所有依赖者都会收到通知并自动更新。

观察者模式提供了一种对象设计,让主题和观察者之间松耦合,Android中的事件机制是典型的观察者模式。
两种实现方式:1、自定义主题和观察者接口;2、使用Java内置观察者模式支持。
举例1:(自定义接口)
    定义subject和observer接口:
1 package com.nwpulisz.observerpattren;
2 public interface Subject {
3     public void registerObserver(Observer o);
4     public void removeObserver(Observer o);
5     public void notifyObservers();
6 }
1 package com.nwpulisz.observerpattren;
2 public interface Observer {
3     public void update(float temp,float humidity,float pressure);
4 }
 
定义display接口,用于显示相应的内容:
1 package com.nwpulisz.observerpattren;
2 public interface Display {
3     public void display();
4 }
 
定义一个主题类,继承subject接口: 
 1 package com.nwpulisz.observerpattren;
 2 import java.util.ArrayList;
 3 public class WeatherData implements Subject {
 4     private ArrayList observers;
 5     private float temperature;
 6     private float humidity;
 7     private float pressure;
 8     public WeatherData(){
 9         observers = new ArrayList();
10     }
11     @Override
12     public void registerObserver(Observer o) {
13         // TODO Auto-generated method stub
14         observers.add(o);
15     }
16     @Override
17     public void removeObserver(Observer o) {
18         // TODO Auto-generated method stub
19         int i = observers.indexOf(o);
20         if (i>=0) {
21             observers.remove(i);
22         }
23     }
24     @Override
25     public void notifyObservers() {
26         // TODO Auto-generated method stub
27         for (int i = 0; i < observers.size(); i++) {
28             Observer observer = (Observer)observers.get(i);
29             observer.update(temperature, humidity, pressure);
30         }
31     }
32     
33     public void measurementChanged(){
34         notifyObservers();
35     }
36     
37     public void setMeasurements(float tempture,float humidity,float pressure){ //用于测试,可以设定数据
38         this.temperature=tempture;
39         this.humidity=humidity;
40         this.pressure=pressure;
41         measurementChanged();
42     }
43 }

 

定义一个观察者类CurrentConditionDisplay类,实现observer接口:
 1 package com.nwpulisz.observerpattren;
 2 public class CurrentConditionDisplay implements Observer,Display {
 3     private float temperature;
 4     private float humidity;
 5     private float pressure;
 6     private Subject weatherData;
 7     
 8     public CurrentConditionDisplay(Subject weatherData){
 9         this.weatherData = weatherData;
10         weatherData.registerObserver(this);
11     }
12     
13     public void update(float temperature, float humidity, float pressure) {
14         // TODO Auto-generated method stub
15         this.temperature = temperature;
16         this.humidity = humidity;
17         this.pressure = pressure;
18         display();
19     }
20     @Override
21     public void display() {
22         // TODO Auto-generated method stub
23         System.out.println("Current conditions,temperature:"+temperature+" humidity:"+
24                     humidity+" pressure:"+pressure);
25     }
26 }

 

定义测试类WeatherStaticon:
 1 package com.nwpulisz.observerpattren;
 2 public class WeatherStation {
 3     
 4     public static void main(String[] args) {
 5         // TODO Auto-generated method stub
 6         WeatherData weatherData = new WeatherData();
 7         Observer currentConditionDisplay = new CurrentConditionDisplay(weatherData);
 8         
 9         weatherData.setMeasurements(22.0f, 23.0f, 25.0f); //output:Current conditions,temperature:22.0 humidity:23.0 pressure:25.0
10         weatherData.setMeasurements(19.0f, 22.3f, 78.9f); //output:Current conditions,temperature:19.0 humidity:22.3 pressure:78.9
11         
12     }
13 }
 
2、使用Java内置的观察者模式
 主题继承observable类观察者继承observer接口,下面的列子用java内置模式实现:
 1 package com.nwpulisz.observerjavapattern;
 2 import java.util.Observable;
 3 public class WeatherData extends Observable {
 4     private float temperature;
 5     private float humidity;
 6     private float pressure;
 7     
 8     public WeatherData(){
 9         
10     }
11     
12     public void measurementChanged(){
13         setChanged();  //Observalbe内置方法,标记状态已经改变的事实;
14                        //查看源码,其实setChanged就是将Changed=true;另外jdk源码中还有方法clearChanged(),通知观察者之前,将changed=false;
15         notifyObservers(); //Observable接口内置方法;
16                         //setChanged之后,才能调用notify方法,这样更有弹性,否则主题变换过于频繁的话,导致主题会不断的通知观察者
17     }
18     
19     public void setMeasurements(float temperature,float humidity,float pressure){
20         this.temperature = temperature;
21         this.humidity = humidity;
22         this.pressure = pressure;
23         measurementChanged();
24     }
25     public float getTemperature() { //不仅仅是主题推送,观察者可以通过get方法,主动“拉”数据;
26         return temperature;
27     }
28     public float getHumidity() {
29         return humidity;
30     }
31     public float getPressure() {
32         return pressure;
33     }
34     
35 }
 1 package com.nwpulisz.observerjavapattern;
 2 import java.util.Observable;
 3 import java.util.Observer;
 4 public class CurrentConditionDisplay implements Observer,Display {
 5     private Observable observable;
 6     private float temperature;
 7     private float humidity;
 8     private float pressure;
 9     
10     public CurrentConditionDisplay(Observable observable){
11         this.observable = observable;
12         observable.addObserver(this);
13     }
14     
15     @Override
16     public void update(Observable o, Object arg) {
17         // TODO Auto-generated method stub
18         if (o instanceof WeatherData) {
19             WeatherData weatherData = (WeatherData)o;
20             this.temperature = weatherData.getTemperature();
21             this.humidity = weatherData.getHumidity();
22             //this.pressure = weatherData.getPressure();
23             display();
24         }
25     }
26     @Override
27     public void display() {
28         // TODO Auto-generated method stub
29         System.out.println("Current conditions,temperature:"+temperature+" humidity:"+
30                 humidity+" pressure:"+pressure);
31     }
32 }

 

定义测试类WeatherStaticon:
 1 package com.nwpulisz.observerjavapattern;
 2 import java.util.Observer;
 3 public class WeatherStation {
 4     
 5     public static void main(String[] args) {
 6         // TODO Auto-generated method stub
 7         WeatherData weatherData = new WeatherData();
 8         Observer currentConditionDisplay = new CurrentConditionDisplay(weatherData);
 9         
10         weatherData.setMeasurements(25.0f, 23.0f, 25.0f); //output:观察者中没有getpress,所以输出结果Current conditions,temperature:25.0 humidity:23.0 pressure:0.0
11         weatherData.setMeasurements(18.0f, 44.3f, 78.9f); //output:观察者中没有getpress,所以输出结果Current conditions,temperature:18.0 humidity:44.3 pressure:0.0
12         
13     }
14 }

 

虽然Java内置了对观察者模式的支持,但是Observable是一个类,而不是一个接口,但是java不支持多继承,可能限制了Observable的复用的能力。
并且看setChanged()方法设计的源码:
1 /**
2      * Marks this <tt>Observable</tt> object as having been changed; the
3      * <tt>hasChanged</tt> method will now return <tt>true</tt>.
4      */
5     protected synchronized void setChanged() {
6         changed = true;
7     }
用protected修饰,因此,除非继承Observable,否则无法创建Observable实例并组合到自己的对象中来,这样就违背了“多用组合,少用继承”的原则。但是Java内置的观察者模式支持也为开发提供了方便,某些情况下只要符合需求也可以直接使用。
在android开发中,事件响应机制,比如构建内部类,对Button的响应,属于观察者模式;同时Android应用开发使用的典型的MVC设计模式,也是观察者模式。
 
 
 





posted @ 2016-04-12 09:30  nwpulisz  阅读(217)  评论(0编辑  收藏  举报