天气站 Java经典案例,观察者模式

ti
提供WeatherData对象,该对象能够获取目前的天气情况
(1)温度
(2)湿度
(3)气压
miaoshu
shuxing

实现思路
silu

//主体接口
public interface Subject {
	public abstract void registerObserver(Observer ob);//注册
	public abstract void removeObserver(Observer ob);//注销
	public abstract void notifyObserver();//通知
}
//更新函数的接口,观察者
//出版者+订阅者=观察者模式
public interface Observer {
	//public abstract是接口的默认的
	public abstract void update(float temperature,float humidity,float pressure);
	//这个接口只用于更新	
}
//主体
import java.util.ArrayList;//集合类型的工具,作用是分配数组空间

public class WeatherData implements subject{
	private float temperature; //温度
	private float humidity; //湿度
	private float pressure;//气压
	
	private ArrayList<Observer> list;//可变数组,list是名字,ArrayList<Observer>是类型
	//在数组里面放观察者类型,不明说是谁的类型,这就是接口的好处
	//list中放的全是各个模版之间的联络方式,也就是地址,地址未带实值
	
	//构造方法
	public WeatherData() {
		list = new ArrayList<Observer>();//数组实例化
	}
	
	//get,set方法
	public float getTemperature(){ 
		return temperature;
	} 
	public float getHumidity(){
		return humidity;
	} 
	public float getPressure(){
		return pressure;
	} 
	
	public void setMeasurement(float t,float h,float p) {
		this.temperature=t;
		this.humidity=h;
		this.pressure=p;
		notifyObserver();
		
	}
	
	//可以编写其他方法

	@Override
	public void registerObserver(Observer ob) {//传入观察者
		// TODO Auto-generated method stub
		list.add(ob);//将指定元素追加到列表末尾
	}

	@Override
	public void removeObserver(Observer ob) {
		// TODO Auto-generated method stub
		if(!list.isEmpty()) {//列表不为空,不为空的时候才能删,空表就没得删
			boolean flag=list.remove(ob);//判断删除是否成功
			if(!flag) {
				System.out.println("删除失败!");
			}
		}
	}

	@Override
	public void notifyObserver() {
		// TODO Auto-generated method stub
		for(Observer one:list) {
			//调用数组中的每一组元素去干活,让每一个0ne都去调用update
			//数组中装的是观察者模版,然后模版调用数据实现功能
			//若是不用接口的话,每个模版都得调用update,同一组数据调用好几遍,墨迹,
			//所以采用one.update()的方式
			one.update(temperature,humidity,pressure);
		}
	}
}

//显示当前温度,湿度和气压
public class CurrentConditionsDisplay implements Observer{
	//类和类之间的通信,当一个类想用另一个类,他们之间一定要有一个通信
	public subject sub;
	//可以写成public WeatherData sub;
	
	public CurrentConditionsDisplay(Subject sub) {
		this.sub=sub;
		sub.register(this);
	}

	@Override
	public void update(float temperature,float humidity,float pressure) {
		// TODO Auto-generated method stub
		System.out.println("温度:"+temperature+";湿度:"+humidity+";气压:"+pressure);
	}

}
//显示出这一次的温度,湿度,气压,比上次高还是低
//这是附加的功能,可写可不写,算是程序的枝叶,不是主干
public class ForecastDisplay implements Observer{
	private float newtemperature; //温度
	private float lasttemperature;
	private float newhumidity; //湿度
	private float lasthumidity;
	private float newpressure;//气压
	private float lastpressure;
	public subject sub;//主题
	
	
	public ForecastDisplay(subject sub) {
		this.sub=sub;
		sub.registerObserver(this);//this是当前类的对象
	}
	
	public String d;
	public String e;
	public String f;
	
	@Override
	public void update(float temperature, float humidity, float pressure) {
		// TODO Auto-generated method stub
		
		this.newtemperature=temperature;
		this.newhumidity=humidity;
		this.newpressure=pressure;
		
		if(newtemperature>lasttemperature ) {
			 d="高于";
		}else if(newtemperature<lasttemperature ) {
			d="低于";
		}else if(newtemperature==lasttemperature) {
			d="等于";
		}
		
				
		if(newhumidity>lasthumidity ) {
			 e="高于";
		}else if(newhumidity<lasthumidity ) {
			e="低于";
		}else if(newhumidity==lasthumidity) {
			e="等于";
		}
		
		if(newpressure>lastpressure ) {
			 f="高于";
		}else if(newpressure<lastpressure ) {
			f="低于";
		}else if(newpressure==lastpressure) {
			f="等于";
		}
		System.out.println("当前温度    "+d+"   之前温度  "+lasttemperature+","+"当前湿度   "+e+"   之前湿度 "+lasthumidity+" ,"+"当前气压   "+f+"   之前气压"+lastpressure);
		
		lasttemperature=this.newtemperature;//给老数据赋上新数据的值
		lasthumidity=this.newhumidity;
		lastpressure=this.newpressure;
	}
	
}
//显示温度的最大,最小,平均值
//这是附加的功能,可写可不写,算是程序的枝叶,不是主干
public class StatisticsDisplay implements Observer{
	//显示温度的最大、最小及平均值
	private float temperature; //温度
	private float maxTem=0;//最大值设个小的,最小值设个大的
	private float minTem=500;
	private float sum=0;
	private int count=0;
	private float avg=0;
	private float humidity; //湿度
	private float pressure;//气压
	public subject sub;//主题
		
	//构造方法
		public StatisticsDisplay(subject sub) {
			this.sub=sub;
			sub.registerObserver(this);//this是当前类的对象
		}
		
		//2.看是否有get,set方法,或其他方法			
		
		@Override
		public void update(float temperature,float humidity,float pressure) {
			this.temperature=temperature;
			this.humidity=humidity;
			this.pressure=pressure;
			
			if(temperature>maxTem) {
				maxTem=temperature;
			}
			if(temperature<minTem) {
				minTem=temperature;
			}
			sum=sum+this.temperature;
			count=count+1;
			display();
		}
	
		public void display() {
			System.out.println("温度最大值:"+maxTem+";温度最小值"+minTem);
			this.avg=sum/count;
			System.out.println("平均值是:"+avg);
		}
		
	}	

//运行
public class TestOne {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		WeatherData weather =new WeatherData();
		CurrentConditionsDisplay current = new CurrentConditionsDisplay(weather);
		
		ForecastDisplay fore =new ForecastDisplay(weather);
		StatisticsDisplay stat=new StatisticsDisplay(weather);
		weather.setMeasurement(14,70, 1010);
		
		//每三秒一组数据(1000毫秒乘3)
		try {
			Thread.sleep(3*1000);//先打这一行,然后点×,选Surround with try/catch
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		weather.setMeasurement(17,70, 1011);
		
		try {
			Thread.sleep(3*1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		weather.setMeasurement(15,71, 1012);
		
		try {
			Thread.sleep(3*1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//weather.removeObserver(fore);//将fore这个模版销毁
	}

}

结果:结果
写代码顺序:
(1)采用了观察者模型,先建立接口,接口分为主体接口和观察者接口;
(2)写主体函数WeatherData,主体函数实现主体接口
(3)写各个模版类,模版类实现观察者接口
(4)写运行类TestOne,输入数据进行测试

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值