想要建立一个应用,利用WeatherData对象取得数据,并更新三个布告板:目前状况,气象统计,和天气预报。
最原始的代码
WeatherData
getTemperature()
getHumidity()
getPressure();
Measure-
mentsChanged()
//一旦气象测量更新,此方法会被调用
Public void measurementsChanged(){
}
现在了解的信息有:
WeatherData类具有getter方法 可以取得三个测量值
当测量数据准备好时,measurementsChanged()方法会调用
实现三个使用天气数据的布告板:目前状况布告板,气象统计布告板,天气预报布告板,
一旦WeatherData有新的测量,这些布告板马上更新
此系统必须可扩展,让其它开发人员建立定制的布告板,用户可以随心所欲添加删除任何布告板.目前布告板有三类:目前状况布告板 气象统计布告板 天气预报布告板.
第一种实现:
Public class WeatherData{
Public void meausrementsChanged(){
Float temp = getTemperature();
Float humidity = getHumidity();
Float pressure = getPressure();
currentConditionDisplay.update(temp,humidity,pressure);
statisticsDisplay.update(temp,humidity,pressure);
forecastDiaplay.update(temp,humidity,pressure);
}
}
布告板更新代码是针对具体实现编程,导致以后增加删除布告板时必须修改程序.
Update方法具有相似性,看起来像一个统一的接口。
观察者模式就好像报社与订报纸的用户之间的关系:
用户向报社预定报纸,报社有新报纸就会给用户发报纸,当用户订阅取消时候,报社就不会给用户发报纸.
在观察者模式中 报社相当于Subject 订阅者为Observer
当主题内的数据改变时候,就会通知观察者。
观察者模式:
定义了对象之间的一对多依赖,这样一来当一个对象改变状态时,它所有的依赖者都会收到通知并且自动更新。
Subject接口具有registerObserver() removeObserver() notifyObservers();
Observer接口 具有方法:update()
主题具有状态,可以控制这些状态,观察者使用这些状态,观察者依赖主题告诉他们状态何时改变了。
产生了一个主题对多个观察者的的关系。
接下来实现气象站的代码
主题接口:
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}
观察者接口
public interface Observer {
public void update(float temp,float humidity,float pressure);
}
显示接口:
public interface DisplayElement {
public void display();
}
气象数据实现主题接口 作为主题 提供数据
public class WeatherData implements Subject {
private ArrayList observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData(){
observers = new ArrayList();
}
@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 notifyObserver() {
for(int i = 0; i < observers.size(); i++){
Observer observer = (Observer)observers.get(i);
observer.update(temperature,humidity,pressure);
}
}
//数据获取来源
public void setMeasurements(float temperature,float humidity,float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
//通知用户更新数据
public void measurementsChanged(){
notifyObserver();
}
}
/**
* Created by Administrator on 2016/2/24.
*/
显示类 实现Observer 作为一个观察者 获取主题的数据
public class CurrentConditionDisplay implements Observer,DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;//保存WeatherData 为了取消注册时用
public CurrentConditionDisplay(Subject weatherData){
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("Current conditions: "+ temperature+"F degrees and" + humidity+" %humidity");
}
@Override
public void update(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
display();
}
}
//测试程序
public class MyClass {
public static void main(String[] args){
WeatherData weatherData = new WeatherData();
CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(weatherData);
weatherData.setMeasurements(10,10,10);
weatherData.setMeasurements(20,20,20);
weatherData.setMeasurements(20,20,30);
}
}
这种方式属于推数据 主题将数据全都给观察者,不管观察者需不需要
还有java sdk 自带观察者类,Observable 主题类
Observer接口 观察者.
Java 自带可以实现 拉数据,观察者可以获得自己想要的数据.
主题类的实现:
package com.gac;
import java.util.Observable;
public class WeatherData extends Observable{
private float temperature;
private float humidity;
private float pressure;
public WeatherData(){
}
public void measurementsChanged(){
//下面的方法都是继承来的
setChanged();//调用notify之前 使用setChanged指示状态已经改变
notifyObservers();//采用拉的方式获取数据 观察者可以获得自己想要的数据
}
//数据获取来源
public void setMeasurements(float temperature,float humidity,float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
//使用拉获取数据时候需要 get方法
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
package com.gac;
import java.util.Observable;
import java.util.Observer;
//观察者类
public class CurrentConditionDisplay implements Observer,DisplayElement{
private Observable observable;
private float temperature;
private float humidity;
public CurrentConditionDisplay(Observable observable){
this.observable = observable;
observable.addObserver(this);
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("Current conditions: "+ temperature+"F degrees and" + humidity+" %humidity");
}
@Override
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
if(o instanceof WeatherData){
WeatherData weatherData = (WeatherData)o;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
}
}
测试程序
package com.gac;
public class MyClass {
public static void main(String[] args){
WeatherData weatherData = new WeatherData();
CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(weatherData);
weatherData.setMeasurements(10,10,10);
weatherData.setMeasurements(20,20,20);
weatherData.setMeasurements(30,30,30);
}
}
总结:
面向对象的基础是:抽象
面向对原则:
封装变化
多用组合,少用继承
针对接口编程,不针对实现编程
为交互对象之间的松耦合设计而努力。