设计模式—Observer Pattern

        在了解Observer Pattern 之前,先看看一个天气监控系统的设计:


        在这个系统中包含三个部分:Weather Station(通过传感器实时获取数据),WeatherData 对象(跟踪Weather Station传输过来的    数据并且更新显示界面),Display device(显示当前有关天气数据)。

        我们现在所要做的是设计一个app,通过利用WeatherData对象来实时显示天气数据:包括当前状况(温度,湿度和气压)、天气数据、一个简单的天气预报。

       以下是WeatherData对象的大致设计:


        现在第一步要做的是实现measurementsChanged()方法,通过它来更新当前状况、天气数据、天气预报信息。(这里切记有三个显示元素)。在实现这个系统的时候同时还要考虑到可扩展性,将来我们可能对显示要素进行不断扩展或删除。

        以下是对实现measurementsChanged()方法进行的第一次尝试:

public class WeatherData {
	//instance variable declarations
	
	public void measurementsChanged(){
		
		float temp = getTemperature();
		float humidity = getHumidity();
		float pressure = getPressure();
		
		currentConditionsDisplay.update(temp,humidity,pressure);//更新第一个显示要素
		statisticsDisplay.update(temp,humidity,pressure);//更新第二个显示要素
		forecastDisplay.update(temp,humidity,pressure);//更新第三个显示要素
		
		//other WeatherData methods here
	}
}

        按照以上的实现的方法,如果我想再增加一个显示元素,那么我不得不对上面的代码进行修改,所以很难维护。

        对于这种问题我们可以利用Observer Pattern,在现实生活中我们经常可以看到Observer Pattern的影子,比如对报纸的订阅,假设某报纸被三个用户甲、乙、丙订阅,那么每当有新版本的报纸发布,他们每人都会得到一份,如果有一天甲用户打电话给出版商取消订阅,那么他就不会继续得到这种服务,如果某一天用户丁觉得这报纸不错,决定订阅,那么他就会收到新版的报纸。

      Observer Pattern的定义:定义了对象之间一对多的相互依赖关系,所以当一个对象(Subject)改变状态的时候,所有依赖这个对象的对象(Observers)将会收到通知并做相应的更新。

        Observer Pattern的类图定义:


        从上图看出(1)只要对象实现了Observer接口,就可以成为Subject中observers变量中的一员。(2)Subject可以随时增加或去除observer对象。(3)任何普通的对象都能够成为observer,只要实现Observer接口,并不需要对对象本身做任何改变。(4)我们可以将Subject和observer对象用作别的用途,因为他们之间的关系不太紧密(低耦合),增加了代码重用性。(5)我们可以随意改动Subject和observer对象,因为他们之间互不影响(低耦合),只要他们实现Subject接口或Observer接口。

        在这里引入另一个设计准则:在设计相互交互的对象时,尽量使这些对象之间处于低耦合的状态。

        我们现在可以将上面的设计方法用于对天气监控系统的设计,将WeatherData对象视为Subject,将各种显示元素视为Observer:




        下面实现以上设计:

        1.接口设计:

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

public interface Observer {
	public void update(float temp,float humidity,float pressure);
}

public interface DisplayElement {
	public void display();
}
        

        2.WeatherData对象设计:

public class WeatherData implements Subject{
	private ArrayList<Observer> observers;
	private float temperature;
	private float humidity;
	private float pressure;
	
	public WeatherData(){
		observers = new ArrayList<Observer>();
	}
	
	public void registerObserver(Observer o){
		observers.add(o);
	}
	
	public void removeObserver(Observer o){
		int i = observers.indexOf(o);
		if(i >= 0){
			observers.remove(i);
		}
	}
	
	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();
	}
}


        3.显示元素设计:

public class CurrentConditionsDisplay implements Observer, DisplayElement {
	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 display() {
		System.out.println("Current conditions: " + temperature +
				"F degrees and " + humidity + "% humidity");
	}

	@Override
	public void update(float temperature, float humidity, float pressure) {
		this.temperature = temperature;
		this.humidity = humidity;
		this.pressure = pressure;
		display();
	}
}

        4.测试代码:


public class WeatherStation {
	public static void main(String[] args){
		WeatherData weatherData = new WeatherData();
		
		CurrentConditionsDisplay currentDisplay = 
				new CurrentConditionsDisplay(weatherData);
		/*StatisticsDisplay statisticsDisplay = 
				new StatisticsDisplay(weatherData);
		ForecastDisplay forecastDisplay = 
				new ForecastDisplay(weatherData);*/
		
		weatherData.setMeasurements(80, 65, 30.4f);//Current conditions: 80.0F degrees and 65.0% humidity
		
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值