设计模式学习--观察者模式
2008-05-15 11:40
519 查看
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。
结构:
例子:
下面以模拟气象站系统来加以说明。
需求分析:
该系统的需求如下:
1、气象站能够追踪目前的天气状况,包括温度、湿度、气压、
2、气象站能够提供三种布告板,分别显示目前天气状况、气象统计和简单的预报。
3、布告板上的数据必须实时更新。
4、气象站必须提供一组API,供其他开发人员开发其他的布告板。
设计部分:
基于以上需求,该系统可以设计成3部分:气象站(获取实际气象数据的物理装置)、WeatherData对象(追踪来自气象站的数据,并更新布告板)和布告板(显示目前的天气状况给用户看)。效果图如下:
错误的类图设计(即没有学过设计模式时的第一感觉)可能如下:
相应的代码实现部分:
这个类图设计的缺点:
1
public void MeasurementsChanged()
2
{
3
temperature = this.GetTemperature(); // 获得温度
4
humidity = this.GetHumidity(); // 获得湿度
5
pressure = this.GetPressure(); // 获得气压
6
7
MyCurrentConditionsDisplay.Update(temperature, humidity, pressure); // 更新目前天气状态板
8
MyStatisticsDisplay.Update(temperature, humidity, pressure); // 更新气象统计板
9
MyForcastDisplay.Update(temperature, humidity, pressure); // 更新天气预报板
10
}
1)、该设计是针对具体实现编程,而非针对接口。
2)、对于每个新的布告板,我们都得修改代码。
3)、我们无法在运动时动态得增加或删除布告板。
4)、我们尚未封装改变的部分。
那么如何改正这些缺点呢?
首先我们必须明白这些缺点的根源在哪里。很明显,我们在类图设计时依赖关系错了,应该依赖倒置。CurrrentConditionsDisplay类、StatisticsDisplay类和ForcastDisplay类应该依赖WeatherData类,而不是相反,这样就可以起到解耦的目的。
其次,CurrrentConditionsDisplay类、StatisticsDisplay类和ForcastDisplay类都有一个Update()方法,因此应该提炼一个接口,这样可以实现“针对接口编程”,使代码更加灵活,也方便其他开发人员开发其他的布告板。
进一步思考:
1)、改正这些缺点后,我们的类图已经与观察者模式的结构有点类似了。
2)、我们的气象站系统的最大问题其实就是一对多的依赖引起的,而观察者模式正是解除一对多关系的不二法门,因此我们有必要采用观察者模式。
采用了观察者模式后设计的类图应该是这样:
WeatherDatea实现ISubject接口,CurrentConditionsDisplay、ForcastDisplay、StatisticsDisplay实现IObserver接口,ISubject调用IObserver,CurrentConditionsDisplay、ForcastDisplay、StatisticsDisplay调用ISubject。
相应的代码实现部分:
1
public class WeatherData : ISubject
2
{
3
private float temperature;
4
private float humidity;
5
private float pressure;
6
private List<IObserver> myList = new List<IObserver>();
7
8
public void SetWeatherData(float paramTemp, float paramHumidity, float paramPressure)
9
{
10
this.temperature = paramTemp;
11
this.humidity = paramHumidity;
12
this.pressure = paramPressure;
13
MeasurementsChanged();
14
}
15
16
public void MeasurementsChanged()
17
{
18
this.NotifyObservers();
19
}
20
21
public void RegisterObserver(IObserver paramIObserver)
22
{
23
myList.Add(paramIObserver);
24
}
25
26
public void RemoveObserver(IObserver paramIObserver)
27
{
28
myList.Remove(paramIObserver);
29
}
30
31
public void NotifyObservers()
32
{
33
foreach (IObserver observer in myList)
34
{
35
observer.Update(temperature, humidity, pressure);
36
}
37
}
38
}
结构:
例子:
下面以模拟气象站系统来加以说明。
需求分析:
该系统的需求如下:
1、气象站能够追踪目前的天气状况,包括温度、湿度、气压、
2、气象站能够提供三种布告板,分别显示目前天气状况、气象统计和简单的预报。
3、布告板上的数据必须实时更新。
4、气象站必须提供一组API,供其他开发人员开发其他的布告板。
设计部分:
基于以上需求,该系统可以设计成3部分:气象站(获取实际气象数据的物理装置)、WeatherData对象(追踪来自气象站的数据,并更新布告板)和布告板(显示目前的天气状况给用户看)。效果图如下:
错误的类图设计(即没有学过设计模式时的第一感觉)可能如下:
相应的代码实现部分:
这个类图设计的缺点:
1
public void MeasurementsChanged()
2
{
3
temperature = this.GetTemperature(); // 获得温度
4
humidity = this.GetHumidity(); // 获得湿度
5
pressure = this.GetPressure(); // 获得气压
6
7
MyCurrentConditionsDisplay.Update(temperature, humidity, pressure); // 更新目前天气状态板
8
MyStatisticsDisplay.Update(temperature, humidity, pressure); // 更新气象统计板
9
MyForcastDisplay.Update(temperature, humidity, pressure); // 更新天气预报板
10
}
1)、该设计是针对具体实现编程,而非针对接口。
2)、对于每个新的布告板,我们都得修改代码。
3)、我们无法在运动时动态得增加或删除布告板。
4)、我们尚未封装改变的部分。
那么如何改正这些缺点呢?
首先我们必须明白这些缺点的根源在哪里。很明显,我们在类图设计时依赖关系错了,应该依赖倒置。CurrrentConditionsDisplay类、StatisticsDisplay类和ForcastDisplay类应该依赖WeatherData类,而不是相反,这样就可以起到解耦的目的。
其次,CurrrentConditionsDisplay类、StatisticsDisplay类和ForcastDisplay类都有一个Update()方法,因此应该提炼一个接口,这样可以实现“针对接口编程”,使代码更加灵活,也方便其他开发人员开发其他的布告板。
进一步思考:
1)、改正这些缺点后,我们的类图已经与观察者模式的结构有点类似了。
2)、我们的气象站系统的最大问题其实就是一对多的依赖引起的,而观察者模式正是解除一对多关系的不二法门,因此我们有必要采用观察者模式。
采用了观察者模式后设计的类图应该是这样:
WeatherDatea实现ISubject接口,CurrentConditionsDisplay、ForcastDisplay、StatisticsDisplay实现IObserver接口,ISubject调用IObserver,CurrentConditionsDisplay、ForcastDisplay、StatisticsDisplay调用ISubject。
相应的代码实现部分:
1
public class WeatherData : ISubject
2
{
3
private float temperature;
4
private float humidity;
5
private float pressure;
6
private List<IObserver> myList = new List<IObserver>();
7
8
public void SetWeatherData(float paramTemp, float paramHumidity, float paramPressure)
9
{
10
this.temperature = paramTemp;
11
this.humidity = paramHumidity;
12
this.pressure = paramPressure;
13
MeasurementsChanged();
14
}
15
16
public void MeasurementsChanged()
17
{
18
this.NotifyObservers();
19
}
20
21
public void RegisterObserver(IObserver paramIObserver)
22
{
23
myList.Add(paramIObserver);
24
}
25
26
public void RemoveObserver(IObserver paramIObserver)
27
{
28
myList.Remove(paramIObserver);
29
}
30
31
public void NotifyObservers()
32
{
33
foreach (IObserver observer in myList)
34
{
35
observer.Update(temperature, humidity, pressure);
36
}
37
}
38
}
相关文章推荐
- 设计模式学习笔记-观察者模式
- 设计模式学习笔记(16)——观察者模式
- 设计模式学习系列十二:观察者模式(Observer)
- 设计模式学习:观察者模式
- 设计模式学习总结——观察者模式
- [知了堂学习笔记]_设计模式之观察者模式
- JavaScript学习之设计模式->观察者模式
- 设计模式学习笔记-观察者模式
- 设计模式学习--------2.观察者模式
- java设计模式学习(一):观察者模式(一)
- 设计模式学习总结-观察者模式(Observer Pattern)
- 设计模式学习-----观察者模式
- 学习、探究Java设计模式——观察者模式
- 步步为营 .NET 设计模式学习笔记 十二、Observer (观察者模式)
- Java-马士兵设计模式学习笔记-观察者模式-OOD 封装event
- Java-马士兵设计模式学习笔记-观察者模式-读取properties文件改成单例模式
- 设计模式学习一 策略模式;观察者模式
- 我是如何学习设计模式的七:中介者模式—和command模式,观察者模式有一定关系
- 设计模式学习-每日一记(14.观察者模式)