观察者模式(Observer Pattern).docx_第1页
观察者模式(Observer Pattern).docx_第2页
观察者模式(Observer Pattern).docx_第3页
观察者模式(Observer Pattern).docx_第4页
观察者模式(Observer Pattern).docx_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

设计模式系列之三:观察者模式(Observer Pattern)收藏观察者模式一、引子气象站监测应用的概况系统分三个部分气象站:获取实际气象数据的物理装置WeatherData对象:追踪来自气象站的数据,并更新布告板。布告板:显示目前天气状况给用户。包括目前状况、气象统计、天气预报。这个项目要完成的任务是:利用WeatherData对象取得数据,并更新三个布告板。二、WeatherData类Class WeatherData getTemperature() getHumidity() getPressure() measurementChanged()1.WeatherData具有getter方法,可以取得三个测量值:温度、湿度和气压。我们不在乎这些值“如何”被设置,WeatherData对象自己知道如何从气象站取得更新数据。2.当新数据备妥时,measurementChanged()方法会被调用(我们不在乎次方法是如何调用,只在乎它被调用了)。3.我们需要实现三个使用天气数据的布告板:目前状况、气象统计、天气预报。4.此系统可以扩展,让其他开发人员建立定制的布告板,用户可以随心所欲地添加或删除任何布告板。二、错误的示范在measurementChanged()方法中添加我们的代码:public class WeatherDatapublic void measurementChanged()float temp = getTemperature();float humidity = getHumidity();float pressure = getPressure();/调用每个布告板更新显示,出入最新的测量。/但是,针对具体实现编程,会导致我们以后增加或删除布告板时必须修改程序。/这是改变的地方,需要封装起来。/不过,至少这里看起来像是一个统一的接口。/布告板的方法名称都是update(),参数都相同。currentConditionsDisplay.update(temp,humidity,pressure);statisticsDisplay.update(temp,humidity,pressure);forecastDisney.update(temp,humidity,pressure);三、认识观察着模式报纸杂志的订阅1.报社的业务就是出版报纸(主题subject)2.向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订户,你就会一直收到新报纸(注册为观察者observer之后,主题就会不断地向观察者发送最新信息)3.当你不想再看报纸时,取消订阅,他们就不会再送新报纸(观察者取消注册,不再是观察者,主题不再发送信息)4.只要报社还在运行,就会一直有人向他们订阅报纸或取消订阅。(可以随时注册成观察者,或者取消注册).出版者+订阅者=观察者模式四、定义观察者模式及类图观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会受到通知并自动更新。类图五、松耦合的威力观察者模式提供了一种对象设计,让主题和观察者之间松耦合。为什么呢?关于观察者的一切,主题只知道观察者实现了某个接口(也就是Observer接口)。主题不需要知道观察者的具体类是谁、做了些什么或其他任何细节。任何时候我们都可以增加新的观察者。因为注意唯一依赖的是一个实现Observer接口的对象列表,事实上,在运行时我们可以用新的观察者取代现有的观察者,主题不会受到任何影响。同样,也可以随时删除某些观察者。有新类型的观察者出现时,主题的代码不需要修改。假如我们有个新的具体类需要当观察者,我不不需要为了兼容新类型而修改主题的代码,所要做的就是在新的类里实现此观察者接口,然后注册为观察者即可。主题不在乎别的,它只会发送通知给所有实现了观察者接口的对象。我们可以独立地复用主题或观察者,因为二者并非紧耦合。改变主题或观察者其中一方,并不会影响另一方。因为两者是松耦合的,所以只要他们之间的接口仍被遵守,我们就可以自由第改变它们。设计原则:为了交互对象直接的松耦合设计而努力。松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的相互依赖降到了最低。六、类图1.主题类2.观察者类3. 气象站类图七、源码观察者模式推push的方式由主题主动将数据送给观察者。拉pull的方式主题提供一些公开的getter方法,让观察者“拉”走需要的数据。辩论:1.主题可以让观察者拉走数据,但是观察者可能需要调用很多次才能收集齐全所要的数据,而推的方式是主题把自己的数据全部传送给观察者,观察者可以在一次通知中得到所有状态数据。2.但是,观察者种类众多,主题不可能事先料到所要观察者的不同需求。观察者直接去拉走需要的数据,这样一来,如果观察者需要一点点数据,就不会强迫受到一堆数据了。同时,也便于以后扩展。如果主题决定增加更多的状态数据,就不用修改和更新对每个观察者的调用,只需改变自己允许更多的getter方法来取得新增的装态。1.推push的方式view plaincopy to clipboardprint?1. ISubject.cs2. 3. interfaceISubject4. 5. 6. 7. /这两个方法都需要观察着做参数,该观察者是用来被注册或删除的8. 9. voidregisterObserver(IObservero);10. 11. voidremoveObserver(IObservero);12. 13. /当主题状态改变时,这个方法被调用,通知所有观察者14. 15. voidnotifyObserver();16. 17. 18. 19. 20. 21. WeatherData.cs22. 23. classWeatherData:ISubject24. 25. 26. 27. /加上一个ArrayList来记录观察者,此ArrayList在构造器中建立。28. 29. privateArrayListobservers;30. 31. privatefloattemperature;32. 33. privatefloathumidity;34. 35. privatefloatpressure;36. 37. publicWeatherData()38. 39. 40. 41. observers=newArrayList();42. 43. 44. 45. #regionISubjectMembers46. 47. /当注册观察者时,我们只要把它加到ArrayList的后面即可48. 49. publicvoidregisterObserver(IObservero)50. 51. 52. 53. observers.Add(o);54. 55. 56. 57. /观察者取消注册,我们把它从ArrayList中删除即可58. 59. publicvoidremoveObserver(IObservero)60. 61. 62. 63. inti=observers.IndexOf(o);64. 65. if(i=0)66. 67. 68. 69. observers.Remove(o);70. 71. 72. 73. 74. 75. /此处,我们把状态告诉每一个观察者。76. 77. /因为观察者都实现了update(),所有我们知道如何通知他们.78. 79. publicvoidnotifyObserver()80. 81. 82. 83. foreach(IObserverobserverinobservers)84. 85. 86. 87. observer.update(temperature,humidity,pressure);88. 89. 90. 91. 92. 93. #endregion94. 95. /从气象站得到更新观测值时,我们通知观察者。96. 97. publicvoidmeasurementsChanged()98. 99. 100. 101. notifyObserver();102. 103. 104. 105. publicvoidsetMeasuremensts(floattemperature,floathumidity,floatpressure)106. 107. 108. 109. this.temperature=temperature;110. 111. this.humidity=humidity;112. 113. this.pressure=pressure;114. 115. measurementsChanged();116. 117. 118. 119. 120. 121. 122. IObserver.cs123. 124. /所有观察者都必须实现update方法,以实现观察者接口。125. 126. interfaceIObserver127. 128. 129. 130. /当气象观测值改变时,主题会把这些状态当作方法的参数,传送给观察者131. 132. voidupdate(floattemp,floathumidity,floatpressure);133. 134. 135. 136. 137. IDisplayElement.cs138. 139. /DisplayElement接口只包含了一个display方法,140. 141. /当布告板需要显示时,调用此方法142. 143. interfaceIDisplayElement144. 145. 146. 147. voiddisplay();148. 149. 150. 151. 152. StatisticsDisplay.cs153. 154. classStatisticsDisplay:IObserver,IDisplayElement155. 156. 157. 158. #regionMembers159. 160. privatefloatmaxTemp=0.0f;161. 162. privatefloatminTemp=200;/setintialhighsothatminimum163. 164. 165. /issetfirstinvokation166. 167. privatefloattemperatureSum=0.0f;168. 169. privateintnumReadings=0;170. 171. privateISubjectweatherData;172. 173. #endregion/Members174. 175. 176. #regionNumberOfReadingsProperty177. 178. publicintNumberOfReadings179. 180. 181. 182. get183. 184. 185. 186. returnnumReadings;187. 188. 189. 190. 191. 192. #endregion/NumberOfReadingsProperty193. 194. 195. #regionConstructor196. 197. publicStatisticsDisplay(ISubjectweatherData)198. 199. 200. 201. this.weatherData=weatherData;202. 203. weatherData.registerObserver(this);204. 205. 206. 207. #endregion/Constructor208. 209. 210. #regionIObserverMembers211. 212. publicvoidupdate(floattemperature,floathumidity,floatpressure)213. 214. 215. 216. temperatureSum+=temperature;217. 218. numReadings+;219. 220. 221. if(temperaturemaxTemp)222. 223. 224. 225. maxTemp=temperature;226. 227. 228. 229. 230. if(temperaturelastPressure)369. 370. 371. 372. str+=Improvingweatherontheway!;373. 374. 375. 376. elseif(currentPressure=lastPressure)377. 378. 379. 380. str+=Moreofthesame;381. 382. 383. 384. elseif(currentPressurelastPressure)385. 386. 387. 388. str+=Watchoutforcooler,rainyweather;389. 390. 391. 392. 393. System.Console.WriteLine(str);394. 395. 396. 397. #endregion398. 399. 400. 401. 402. 403. Program.cs404. 405. classProgram406. 407. 408. 409. staticvoidMain(stringargs)410. 411. 412. 413. WeatherDataweatherData=newWeatherData();414. 415. CurrentConditionsDisplaycurrentDisplay=newCurrentConditionsDisplay(weatherData);416. 417. ForcastDisplayforcastDisplay=newForcastDisplay(weatherData);418. 419. StatisticsDisplaystatisticsDisplay=newStatisticsDisplay(weatherData);420. 421. weatherData.setMeasuremensts(80,65,30.4F);422. 423. 424. 425. 2.拉pull的方式以WeatherData.cs和CurrentConditionsDisplay.cs为例进行说明view plaincopy to clipboardprint?1. WeatherData.cs2. 3. classWeatherData:ISubject4. 5. 6. 7. /加上一个ArrayList来记录观察者,此ArrayList在构造器中建立。8. 9. privateArrayListobservers;10. 11. privatefloattemperature;12. 13. privatefloathumidity;14. 15. privatefloatpressure;16. 17. publicWeatherData()18. 19. 20. 21. observers=newArrayList();22. 23. 24. 25. #regionISubjectMembers26. 27. /当注册观察者时,我们只要把它加到ArrayList的后面即可28. 29. publicvoidregisterObserver(IObservero)30. 31. 32. 33. observers.Add(o);34. 35. 36. 37. /观察者取消注册,我们把它从ArrayList中删除即可38. 39. publicvoidremoveObserver(IObservero)40. 41. 42. 43. inti=observers.IndexOf(o);44. 45. if(i=0)46. 47. 48. 49. observers.Remove(o);50. 51. 52. 53. 54. 55. 56. /此处,我们把状态告诉每一个观察者。57. 58. /因为观察者都实现了update(),所有我们知道如何通知他们.59. 60. publicvoidnotifyObserver()61. 62. 63. 64. foreach(IObserverobserverinobservers)65. 66. 67. 68. observer.update();69. 70. 71. 72. 73. 74. #endregion75. 76. 77. /从气象站得到更新观测值时,我们通知观察者。78. 79. publicvoidmeasurementsChanged()80. 81. 82. 83. notifyObserver();84. 85. 86. 87. publicvoidsetMeasuremensts(floattemperature,floathumidity,floatpressure)88. 89. 90. 91. this.temperature=temperature;92. 93. this.humidity=humidity;94. 95. this.pressure=pressure;96. 97. measurementsChanged();98. 99. 100. 101. 102. publicfloatgetTemperature()103. 104. 105. 106. returntemperature;107. 108. 109. 110. publicfloatgetHumidity()111. 112. 113. 114. returnhumidity;115. 116. 117. 118. publicfloatgetPressure()119. 120. 121. 122. returnpressure;123. 124. 125. 126. 127. 128. 129. 130. CurrentConditionsDisplay.cs131. 132. classCurrentConditionsDisplay:IObserver,IDisplayElement133. 134. 135. 136. privatefloattemperature;137. 138. privatefloathumidity;139. 140. privateISubjectweatherData;141. 142. publicCurrentConditionsDisplay(ISubjectweatherData)143. 144. 145. 146. this.weatherData=weatherData

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论