1.首先看观察者模式定义:
对象之间有一对多的依赖关系,一个对象状态改变,会通知其他对象,其他对象会自动更新。
2.主题对象(被观察者)提供观察接口,多个观察者实现此接口。
3.JDK中Swing,JavaBeans等都有使用该模式。
4.现在来看代码
5.先看主题接口Subject:定义一个接口
1 package com.pattern.observer; 2 /* 3 * 主题接口,只知道有观察者观察它,对于观察者并不是很了解,主题对象要实现此接口 4 * */ 5 public interface Subject { 6 7 void registerObserver(Observer o);//注册观察者,或者说登记 8 void removeObserver(Observer o);//取消一个观察者 9 void notifyAllObserver();//通知所有观察者 10 11 }
6.定义观察者接口Observer
1 package com.pattern.observer; 2 /* 3 * 观察者接口,所有的观察者都要实现这个接口,并实现接口里的uodate方法 4 */ 5 public interface Observer { 6 void update(Object o);//所有的观察者都有更新自己的方法,主题对象会调用此方法把数据传给观察者 7 }
7.定义主题接口实现者(由自己实际决定)WeatherForecast
1 package com.pattern.observer; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /* 7 * 主题对象,天气预报 8 */ 9 public class WeatherForecast implements Subject { 10 11 private List<Observer> observers;//所有注册的观察者 12 private WeatherData data;//状态的引用 13 14 15 public WeatherForecast( WeatherData data) { 16 super(); 17 this.observers = new ArrayList<Observer>(); 18 this.data = data; 19 } 20 21 @Override 22 public void registerObserver(Observer o) { 23 observers.add(o); 24 25 } 26 27 @Override 28 public void removeObserver(Observer o) { 29 observers.remove(o); 30 31 } 32 33 //通知所有观察者 34 @Override 35 public void notifyAllObserver() { 36 for (Observer observer : observers) { 37 observer.update(data); 38 } 39 40 } 41 42 //从气象站获取的测量值发生改变会调用此方法 43 public void measurementDataChanged(){ 44 notifyAllObserver(); 45 } 46 //改变状态 47 public void setWeatherData(WeatherData data){ 48 this.data = data; 49 50 } 51 52 }
8.定义主题对象的状态类,或者说是数据对象WeatherData
package com.pattern.observer; /* * 天气数据封装类,或者说主题对象的状态封装类 */ public class WeatherData { private float temperature;//温度数据,一个状态 private float humidity;//湿度数据,一个状态 private float pressure;//压力数据,一个状态 public WeatherData(float temperature, float humidity, float pressure) { super(); this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; } public void setState(float temperature, float humidity, float pressure) { this.setTemperature(temperature); this.setHumidity(humidity); this.setPressure(pressure); } public float getTemperature() { return temperature; } public void setTemperature(float temperature) { this.temperature = temperature; } public float getHumidity() { return humidity; } public void setHumidity(float humidity) { this.humidity = humidity; } public float getPressure() { return pressure; } public void setPressure(float pressure) { this.pressure = pressure; } }
9.定义所有的观察者类,我在此处定义了两个CurrentWeatherDisplay和FeatureWeather,代码如下
1 package com.pattern.observer; 2 /* 3 * 观察者对象之一,当前天气显示面板 4 */ 5 public class CurrentWeatherDisplay implements Observer { 6 private WeatherData data;//接受传过来的数据对象 7 private Subject sj;//表示要注册的主题或者说广播 8 9 public CurrentWeatherDisplay(){ 10 11 } 12 public CurrentWeatherDisplay(Subject sj) {//构造方法需要主题作为注册之用 13 super(); 14 this.sj = sj; 15 sj.registerObserver(this);//一旦创建好观察者对象就把注册到主题列表中 16 } 17 /* 18 * 把自己注册一个主题 19 */ 20 public void register(Subject sj){ 21 this.sj = sj; 22 sj.registerObserver(this); 23 } 24 /* 25 * 取消注册一个主题 26 */ 27 public void unregister(Subject sj){ 28 this.sj = sj; 29 sj.removeObserver(this); 30 this.sj = null; 31 } 32 33 @Override 34 public void update(Object o) { 35 this.data = (WeatherData) o; 36 display();//天气数据一旦改变,马上更新面板 37 } 38 39 public void display(){ 40 System.err.println("目前的天气是--温度:"+data.getTemperature()+"湿度:"+data.getHumidity()+"气压:"+data.getPressure()); 41 } 42 43 }
1 package com.pattern.observer; 2 /* 3 * 观察者对象之一,未来天气显示面板 4 */ 5 public class FeatureWeather implements Observer { 6 private WeatherData data;//接受传过来的数据对象 7 private Subject sj;//表示要注册的主题或者说广播 8 9 public FeatureWeather(){ 10 11 } 12 public FeatureWeather(Subject sj) {//构造方法需要主题作为注册之用 13 super(); 14 this.sj = sj; 15 sj.registerObserver(this);//一旦创建好观察者对象就把注册到主题列表中 16 } 17 /* 18 * 把自己注册一个主题 19 */ 20 public void register(Subject sj){ 21 this.sj = sj; 22 sj.registerObserver(this); 23 } 24 /* 25 * 取消注册一个主题 26 */ 27 public void unregister(Subject sj){ 28 this.sj = sj; 29 sj.removeObserver(this); 30 this.sj = null; 31 } 32 33 @Override 34 public void update(Object o) { 35 this.data = (WeatherData) o; 36 display(); 37 38 } 39 40 public void display(){ 41 System.err.println("未来几天的天气是--温度:"+data.getTemperature()+1.0+"-"+data.getTemperature()+10.0+"湿度:"+data.getHumidity()+2.0+"-"+data.getHumidity()+6.0+"气压:"+data.getPressure()+"-"+data.getPressure()+2.0); 42 } 43 44 }
10.测试客户端代码
1 package com.pattern.observer; 2 /** 3 * 客户端测试代码 4 * @author Administrator 5 * 6 */ 7 public class Client { 8 9 public static void main(String[] args) { 10 WeatherData data = new WeatherData(25.0F, 0.46F, 1.1F);//天气数据 11 Subject sj = new WeatherForecast(data);//主题对象天气站 12 CurrentWeatherDisplay cw = new CurrentWeatherDisplay();//目前天气观察者,显示板块 13 FeatureWeather fw = new FeatureWeather();//未来天气板块 14 cw.register(sj);//注册 15 fw.register(sj); 16 sj.notifyAllObserver();//通知 17 data.setState(30.0F, 0.58F, 1.3F);//主题状态改变 18 ((WeatherForecast) sj).setWeatherData(data);//数据发生改变 19 20 21 22 } 23 24 }
11.测试结果截
12.设计模式在使用框架时候很方便,当然也可以使用模式自己开发框架