设计模式入门-观察者模式

      现在是大三寒假,在大二暑假时进入国内某互联网上市公司做Android开发,半年多的学习和工作积累了很多,刚好现在下班后不用急的赶回去上课,就留在公司写博客总结一下。《设计模式》这本经典的书是之前在公交车上读的,现在计划每隔一段时间总结一个专题,回顾一下。今天回顾一下第一个模式:观察者模式。由于本人能力有限,这也是本人写的第一篇博客,有错误的地方希望各位大神指点。

认识观察者模式

举一个生活中的例子,报社的业务是出版报纸,如果你向报社订阅了报纸,那么他们只要有新报纸出版,就会给你送来,如果你不想看了,可以取消订阅,那么他们就不会把报纸送来了。他们可以有很多个订阅者,只要报社在运营,就会一直有人想他们订阅或取消订阅报纸。

出版者+订阅者=观察者模式

     如果你了解了的订阅是怎么回事,那么你就明白了观察者模式是怎么回事,在这里“出版者”被称为“主题”(Subject),“订阅者”被称为“观察者”(Observer)。

                 

观察者模式

        定义了对象之间的一对多依赖,当一个对象发生改变时,它所有的依赖者就会搜到通知,并自动更新。

式中的角色

    1.抽象主题角色(Subject):目标角色知道它的观察者,可以有任意多个观察者观察同一个目标。并且提供注册和删除观察者对象的接口。目标角色往往由抽象类或者接口来实现。

    2. 抽象观察者角色(Observer):为那些在目标发生改变时需要获得通知的对象定义一个更新接口。抽象观察者角色主要由抽象类或者接口来实现。

    3.具体主题角色(Concrete Subject):将有关状态存入各个Concrete Observer对象。当它的状态发生改变时, 向它的各个观察者发出通知。

    4.具体观察者角色(Concrete Observer):存储有关状态,这些状态应与目标的状态保持一致。实现Observer的更新接口以使自身状态与目标的状态保持一致。在本角色内也可以维护一个指向Concrete Subject对象的引用。

 实际工程项目中的应用

     下面来结合一个实际工程项目:气象监测站会将传感器收集到的数据(温度Temperature,湿度Humidity,气压Pressure)传给WeatherData对象,利用该对象来实时更新显示三个布告板:目前天气状况(CurrentConditions),气象统计(Statistics)和天气预报(Forecast)。

     观察者模式定义了一对多的依赖关系,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并更新。那么WeatherData类就是“一”,“多”就是使用天气观测的各种布告板。我们把WeatherData对象当做“主题(Subject)",把布告板当做观察者,布告板为了取得信息,向WeatherData对象注册。一旦WeatherData对象知道某个布告板的存在,就会调用update方法,来对布告板进行更新。update是在观察者Observer接口中定义的。

类图



实现代码

主题Subject接口:利用该接口中的函数可以注册,移除和通知观察者

public interface Subject {
    
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObservers();

}

观察者Observer接口:主题通过调用update方法来通知各个实现Observer接口的观察者们。

public interface Observer {
    
    public void update(float temp,float humidity,float pressure);
}
具体主题角色(Concrete Subject)

</pre><pre name="code" class="java">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 notifyObservers() {
		for(int i=0;i<observers.size();i++){
			Observer observer=(Observer)observers.get(i);
			observer.update(temperature,humidity,pressure);
		}
	}
	
	public void measurementsChanged(){
		notifyObservers();
	}
	
	public void setMeasurements(float temperature,float humidity,float pressure){
		this.temperature=temperature;
		this.humidity=humidity;
		this.pressure=pressure;
		measurementsChanged();
	}

}

具体观察者角色CurrentConditionDisplay

public class CurrentConditionsDisplay implements Observer{
	
	private float temperature;
	private float humidity;
	private float pressure;
	private Subject weatherData;
	
	public CurrentConditionsDisplay(Subject weatherData){
		this.weatherData=weatherData;
		weatherData.registerObserver(this);
	}
	
	@Override
	public void update(float temp, float humidity, float pressure) {
		this.temperature=temp;
		this.humidity=humidity;
		this.pressure=pressure;
		System.out.println("当前天气状态 :"+temperature+"度 , "+humidity+
				"湿度 和 "+pressure+"帕");
	}
}

具体观察者角色StatisticsDisplay

public class StatisticsDisplay implements Observer{
	
	private float temperature;
	private float humidity;
	private float pressure;
	private Subject weatherData;

	public StatisticsDisplay(Subject weatherData){
		this.weatherData=weatherData;
		weatherData.registerObserver(this);
	}
	
	@Override
	public void update(float temp, float humidity, float pressure) {
		this.temperature=temp;
		this.humidity=humidity;
		this.pressure=pressure;
		System.out.println("统计天气显示 :"+temperature+"度 , "+humidity+
				"湿度 和 "+pressure+"帕");
	}

}


具体观察者角色ForecastDisplay

public class ForecastDisplay implements Observer{
	
	private float temperature;
	private float humidity;
	private float pressure;
	private Subject weatherData;

	public ForecastDisplay(Subject weatherData){
		this.weatherData=weatherData;
		weatherData.registerObserver(this);
	}
	
	@Override
	public void update(float temp, float humidity, float pressure) {
		this.temperature=temp;
		this.humidity=humidity;
		this.pressure=pressure;
		System.out.println("预测天气显示 :"+temperature+"度 , "+humidity+
				"湿度 和 "+pressure+"帕");
	}

}

测试代码
public class WeatherStation {
	
	public static void main(String []args){
		//首先建立一个主题WeatherData对象
		WeatherData weatherData=new WeatherData();
		//创建3个布告板
		CurrentConditionsDisplay currentDisplay=new CurrentConditionsDisplay(weatherData);
		StatisticsDisplay statisticsDisplay=new StatisticsDisplay(weatherData);
		ForecastDisplay forecastDisplay=new ForecastDisplay(weatherData);
		//模拟气象测量
		weatherData.setMeasurements(80,65, 30.4f);
	}

}

输出结果
当前天气状态 :80.0度 , 65.0湿度 和 30.4帕
统计天气显示 :80.0度 , 65.0湿度 和 30.4帕
预测天气显示 :80.0度 , 65.0湿度 和 30.4帕


模式总结

       观察者模式提供了一种对象设计,让主题和观察者之间松耦合。让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。 但是依赖关系并未完全解除,抽象通知者依旧依赖抽象的观察者。因为主题在调用观察者的update方法时把内部的成员传给了观察者,而且对于不同的观察者可能需要不同的参数。Java内置了观察者模式,有推push和拉pull两种。后续会使用java内置的观察者模式来实现。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值