1.OO角度
1、Internet气象站项目:
提供温度、气压和湿度的接口
测量数据更新时需时时通知给第三方
需要设计开放型API,便于其他第三方公司也能接入气象站获取数据
WeatherData 类
package com.java.hexter.internetweather;
/**
* 天气数据的公共接口
* 提供温度、气压和湿度的接口
* 测量数据更新时需时时通知给第三方
* 需要设计开放型API,便于其他第三方公司也能接入气象站获取数据
*/
public class WeatherData {
/**
* 温度 压力 湿度 属性
*/
private float mTemperatrue;
private float mPressure;
private float mHumidity;
/**
* 气象台提供的新数据
*/
private CurrentConditions mCurrentConditions;
public WeatherData(CurrentConditions mCurrentConditions) {
this.mCurrentConditions = mCurrentConditions;
}
/**
* 获取数据
* @return 天气
*/
public float getTemperature() {
return mTemperatrue;
}
/**
* 获取数据
* @return 压力
*/
public float getPressure() {
return mPressure;
}
/**
* 获取数据
* @return 湿度
*/
public float getHumidity() {
return mHumidity;
}
/**
* 当有了新的天气参数,将天气数据进行更新,并进行通知
*/
public void dataChange() {
mCurrentConditions.update(getTemperature(), getPressure(), getHumidity());
}
/**
* 设置新的天气数据 将传递的参数进行设置,并调用相应接口进行通知
* @param mTemperature
* @param mPressure
* @param mHumidity
*/
public void setData(float mTemperature, float mPressure, float mHumidity) {
this.mTemperatrue = mTemperature;
this.mPressure = mPressure;
this.mHumidity = mHumidity;
dataChange();
}
}
通知类
package com.java.hexter.internetweather;
/**
* 进行具体的通知
*/
public class CurrentConditions {
private float mTemperature;
private float mPressure;
private float mHumidity;
public void update(float mTemperature,float mPressure,float mHumidity)
{
this.mTemperature=mTemperature;
this.mPressure=mPressure;
this.mHumidity=mHumidity;
display();
}
public void display()
{
System.out.println("***Today mTemperature: "+mTemperature+"***");
System.out.println("***Today mPressure: "+mPressure+"***");
System.out.println("***Today mHumidity: "+mHumidity+"***");
}
}
Demo
package com.java.hexter.internetweather;
/**
* 模拟气象台提供天气数据
*/
public class InternetWeather {
public static void main(String[] args) {
CurrentConditions mCurrentConditions;
WeatherData mWeatherData;
mCurrentConditions = new CurrentConditions();
mWeatherData = new WeatherData(mCurrentConditions);
// 气象台设置天气。当天气发送改变时会调用调用通知
mWeatherData.setData(30, 150, 40);
mWeatherData.setData(302, 1502, 402);
/**
* 传统面向对象进行设置的弊端
* 当有新的天气通知时,不能同时进行通知,功能单一
* 例如:目前只能进行通知当前的天气,如果需要进行通知更多的天气时间。需要修改代码、
*/
}
}
2.使用观察者模式解决上述问题
Subject 接口
/**
* 被观察者(生产者) 接口
* 提供共有的注册 删除 通知 接口
*/
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
Observer接口
package com.java.hexter.internetweather.observer;
/**
* 观察者接口 (消费者)
*/
public interface Observer {
public void update(float mTemperatrue,float mPressure,float mHumidity);
}
WeatherDataSt 被观察者实现
package com.java.hexter.internetweather.mode;
import java.util.ArrayList;
import com.java.hexter.internetweather.observer.Observer;
import com.java.hexter.internetweather.observer.Subject;
/**
* 使用观察值模式 将天气数据信息与进行通知进行分离
*/
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();
}
/**
* 设置天气数据调用通知方法
* @param mTemperatrue
* @param mPressure
* @param mHumidity
*/
public void setData(float mTemperatrue, float mPressure, float mHumidity) {
this.mTemperatrue = mTemperatrue;
this.mPressure = mPressure;
this.mHumidity = mHumidity;
dataChange();
}
/**
* 注册观察者
* @param o
*/
@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() {
// TODO Auto-generated method stub
for (int i = 0, len = mObservers.size(); i < len; i++) {
mObservers.get(i).update(getTemperature(), getPressure(), getHumidity());
}
}
}
观察者实例
package com.java.hexter.internetweather.mode;
import com.java.hexter.internetweather.observer.Observer;
/**
* 观察者实例
*/
public class ForcastConditions implements Observer {
private float mTemperatrue;
private float mPressure;
private float mHumidity;
/**
* 进行通知
* @param mTemperatrue
* @param mPressure
* @param 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()) + "**");
}
}
package com.java.hexter.internetweather.mode;
import com.java.hexter.internetweather.observer.Observer;
/**
* 观察者实例
*/
public class CurrentConditions implements Observer {
private float mTemperatrue;
private float mPressure;
private float mHumidity;
/**
* 进行通知
* @param mTemperatrue
* @param mPressure
* @param 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 + "***");
}
}
Demo
package com.java.hexter.internetweather.mode;
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);
// 再次进行通知,会通知所有存在的观察者
System.out.println("===========");
mWeatherDataSt.setData(40, 250, 50);
/**
* 观察者模式的好处,将观察者与被观察者进行分离解耦,
* 被观察者无需知道有哪些观察者,只是对所有的观察者提供注册、删除、通知的功能。观察者则只需进行对应的通知业务
* 操作更加的灵活,可以在运行时动态的添加删除观察者
*/
}
}
观察者模式: 对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对 象为Observer,Subject通知Observer变化
3.java内置观察者
1、Java内置的观察者 Observable Observer
2、内置观察者的注意点 Observable是类而不是接口
WeatherData (被观察者)
package com.java.hexter.internetweather.jv;
import java.util.Observable;
/**
* java内置观察者模式
* 被观察者(生产者)继承 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;
}
public void dataChange() {
// 注明数据发生了变化;
this.setChanged();
// 通知列表中的所有observer 并执行observer的update方法
this.notifyObservers(new Data(getTemperature(), getPressure(), getHumidity()));
}
/**
* 当天气发生改变时 掉用java内置的通知方法
* @param mTemperatrue
* @param mPressure
* @param mHumidity
*/
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;
}
}
}
ForcastConditions 实例观察者
package com.java.hexter.internetweather.jv;
import java.util.Observable;
import java.util.Observer;
import com.java.hexter.internetweather.jv.WeatherData.Data;
/**
* observer 观察者
*/
public class ForcastConditions implements Observer {
private float mTemperatrue;
private float mPressure;
private float mHumidity;
/**
* 接收被观察者的通知 执行相应的逻辑
* @param arg0
* @param arg1
*/
@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) + "***");
}
}
Demo
package com.java.hexter.internetweather.jv;
public class InternetWeather {
public static void main(String[] args) {
// 创建观察者 以及被观察者实例
CurrentConditions mCurrentConditions;
ForcastConditions mForcastConditions;
WeatherData mWeatherData;
mCurrentConditions = new CurrentConditions();
mForcastConditions = new ForcastConditions();
mWeatherData = new WeatherData();
/**
* 将观察者mCurrentConditions、mForcastConditions注册到mWeatherData被观察者中
*/
mWeatherData.addObserver(mCurrentConditions);
mWeatherData.addObserver(mForcastConditions);
// 设置数据。当数据被设置时会进行通知所有的观察者observer
mWeatherData.setData(30, 150, 40);
System.out.println("==================");
// 删除一个observer 再次通知
mWeatherData.deleteObserver(mCurrentConditions);
mWeatherData.setData(35, 150, 60);
}
}