观察者模式
在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知并自动更新。
设计原则
封装变化;多用组合,少用继承;针对接口编程,不针对实现编程;为交互对象之间的松耦合设计而努力。
示例:气象监测
类图设计
Subject接口
public interface Subject {
public void registerObserver(Observer o);//注册观察者
public void removeObserver(Observer o);//移除观察者
public void notifyObservers();//通知观察者
}
Observer接口
public interface Observer {
public void update(float mTemperatrue,float mPressure,float mHumidity);
}
Subject实现类WeatherDataSt
public class WeatherDataSt implements Subject{
private float mTemperatrue;//温度
private float mPressure;//气压
private float mHumidity;//湿度
private ArrayList<Observer> mObservers;//观察者集合
public WeatherDataSt(){
mObservers=new ArrayList<Observer>();
}
public float getTemperature(){
return mTemperatrue;
}
public float getPressure(){
return mPressure;
}
public float getHumidity(){
return mHumidity;
}
public void dataChange(){
notifyObservers();
}
public void setData(float mTemperatrue,float mPressure,float mHumidity){
this.mTemperatrue=mTemperatrue;
this.mPressure=mPressure;
this.mHumidity=mHumidity;
dataChange();
}
@Override
public void registerObserver(Observer o) {
// TODO Auto-generated method stub
mObservers.add(o);
}
@Override
public void removeObserver(Observer o) {
// TODO Auto-generated method stub
if(mObservers.contains(o))
{mObservers.remove(o);}
}
@Override
public void notifyObservers() {
// 遍历观察者集合给所有注册的观察者推送更新数据
for(int i=0,len=mObservers.size();i<len;i++)
{
mObservers.get(i).update(getTemperature(), getPressure(), getHumidity());
}
}
}
观察者CurrentConditions
public class CurrentConditions implements Observer {
private float mTemperatrue;
private float mPressure;
private float mHumidity;
@Override
public void update(float mTemperatrue, float mPressure, float mHumidity) {
// TODO Auto-generated method stub
this.mHumidity = mHumidity;
this.mPressure = mPressure;
this.mTemperatrue = mTemperatrue;
display();
}
public void display() {
System.out.println("***Today mTemperatrue:" + mTemperatrue + "***");
System.out.println("***Today mPressure:" + mPressure + "***");
System.out.println("***Today mHumidity:" + mHumidity + "***");
}
}
观察者ForcastConditions
public class ForcastConditions implements Observer{
private float mTemperatrue;
private float mPressure;
private float mHumidity;
@Override
public void update(float mTemperatrue, float mPressure, float mHumidity) {
// TODO Auto-generated method stub
this.mTemperatrue=mTemperatrue;
this.mPressure=mPressure;
this.mHumidity=mHumidity;
display();
}
public void display()
{
System.out.println("**明天温度:"+(mTemperatrue+Math.random())+"**");
System.out.println("**明天气压:"+(mPressure+10*Math.random())+"**");
System.out.println("**明天湿度:"+(mHumidity+Math.random())+"**");
}
}
测试InternetWeather
public class InternetWeather {
public static void main(String[] args) {
CurrentConditions mCurrentConditions;
ForcastConditions mForcastConditions;
WeatherDataSt mWeatherDataSt;
mWeatherDataSt=new WeatherDataSt();
mCurrentConditions=new CurrentConditions();
mForcastConditions=new ForcastConditions();
mWeatherDataSt.registerObserver(mCurrentConditions);
mWeatherDataSt.registerObserver(mForcastConditions);
mWeatherDataSt.setData(30, 150, 40);
mWeatherDataSt.removeObserver(mCurrentConditions);
mWeatherDataSt.setData(40, 250, 50);
}
}
java内置观察者模式
用jdk内置的观察者模式重构项目
WeatherData继承Observable
//Observable是一个类
public class WeatherData extends Observable{
private float mTemperatrue;
private float mPressure;
private float mHumidity;
public float getTemperature(){
return mTemperatrue;
}
public float getPressure(){
return mPressure;
}
public float getHumidity(){
return mHumidity;
}
//notifyObservers(arg)的做法是(push)推,把数据当做对象传输
//notifyObservers()的做法是(pull)拉,观察者的数据就得WeatherData对象中获取
public void dataChange(){
this.setChanged();//在notifyObservers()之前一定要调用setChange()否则会推送失败
this.notifyObservers(new Data(getTemperature(),getPressure(),getHumidity()));
}
public void setData(float mTemperatrue,float mPressure,float mHumidity){
this.mTemperatrue=mTemperatrue;
this.mPressure=mPressure;
this.mHumidity=mHumidity;
dataChange();
}
//数据传输对象
public class Data{
public float mTemperatrue;
public float mPressure;
public float mHumidity;
public Data(float mTemperatrue,float mPressure,float mHumidity)
{
this.mTemperatrue=mTemperatrue;
this.mPressure=mPressure;
this.mHumidity=mHumidity;
}
}
}
CurrentConditions实现Observer接口
public class CurrentConditions implements Observer {
private float mTemperatrue;
private float mPressure;
private float mHumidity;
@Override
public void update(Observable arg0, Object arg1) {
// TODO Auto-generated method stub
this.mTemperatrue=((Data)(arg1)).mTemperatrue;
this.mPressure=((Data)(arg1)).mPressure;
this.mHumidity=((Data)(arg1)).mHumidity;
display();
}
public void display()
{
System.out.println("***Today mTemperatrue:" +mTemperatrue+"***");
System.out.println("***Today mPressure:" +mPressure+"***");
System.out.println("***Today mHumidity:" +mHumidity+"***");
}
}
CurrentConditions实现Observer接口
public class ForcastConditions implements Observer {
private float mTemperatrue;
private float mPressure;
private float mHumidity;
@Override
public void update(Observable arg0, Object arg1) {
// TODO Auto-generated method stub
this.mTemperatrue=((Data)(arg1)).mTemperatrue;
this.mPressure=((Data)(arg1)).mPressure;
this.mHumidity=((Data)(arg1)).mHumidity;
display();
}
public void display(){
System.out.println("***Tomorrow mTemperatrue:" +(mTemperatrue+1)+"***");
System.out.println("***Tomorrow mPressure:" +(mPressure+1)+"***");
System.out.println("***Tomorrow mHumidity:" +(mHumidity+1)+"***");
}
}
测试InternetWeather
public class InternetWeather {
public static void main(String[] args) {
CurrentConditions mCurrentConditions;
ForcastConditions mForcastConditions;
WeatherData mWeatherData;
mCurrentConditions=new CurrentConditions();
mForcastConditions=new ForcastConditions();
mWeatherData=new WeatherData();
mWeatherData.addObserver(mCurrentConditions);
mWeatherData.addObserver(mForcastConditions);
mWeatherData.setData(30, 150, 40);
mWeatherData.deleteObserver(mCurrentConditions);
mWeatherData.setData(35, 150, 60);
}
}