




已阅读5页,还剩5页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
描述:在设计一组依赖的对象与它们所依赖的对象之间一致(同步)的交流模型时,观察者模式(ObserverPattern)很有用。它可以使依赖对象的状态与它们所依赖的对象的状态保持同步。这组依赖的对象指的是观察者(Observer),它们所依赖的对象称为主题(Subject)。为了实现观察者(Observer)的状态与主题(Subject)保持同步,观察者模式(ObserverPattern)推荐采用发布者-订阅者(publisher-subscriber)模型,以使这组观察者(Observer)和主题(Subject)对象之间有清晰的界限。典型的观察者(Observer)是一个依赖于或者关注于主题对象的状态的对象。一个主题可以有一个或者多个观察者。这些观察者在主体的状态发生变化时,需要得到通知。由于给定主体的观察者链表需要动态的变化,因此一个主题不能维护一个静态的观察者链表。因此关注于主题状态的任何对象都需要明确地注册自己为主体的一个观察者。主题状态发生的变化,都需要通知所有的以注册的观察者。从主题接到通知以后,每一个观察者查询主题,使自己的状态与主题的同步。因此一个主题扮演着发布者的角色,发布信息到所有的以订阅的观察者。换句话说,主题和它的观察者之间包含了一对多的关系。当主题的实例的状态发生变化时,所有的依赖于它的观察者都会得到通知并更新自己。每一个观察者对象需要向主题注册,当主题的状态发生变化的时候得到通知。一个观察者可以注册或者订阅多个主题。当观察者不希望再得到通知时,它可以向主题进行注销。为了实现这种机制:(1)主题需要为注册和注销通知提供一个接口。(2)下面的两点也需要满足:A、拉模型(Inthepullmodel)-主题需要提供一个接口,可以使观察者查询主题获得需要的状态信息来更新自己的状态。B、推模型(Inthepushmodel)-主题发送观察者可能关注的状态信息。(3)观察者需要提供一个可以从主题接受通知的接口。类图(图33.1)描述了为满足于以上需求,不同类的结构和它们之间的关联关系。Figure33.1:GenericClassAssociationWhentheObserverPatternIsApplied从这个类图可以看到:(1)所有的主题需要提供一个类似于Observable接口的实现。(2)所有的观察者需要提供一个类似于Observer接口的实现。在应用观察者模式时,有几种变体。这就会产生不同类型的主题-观察者模式,例如,观察者仅关注主体特定类型的变化等。增加新的观察者:应用观察者模式以后,在不影响主题类的情况下,可以动态的加入不同的观察者。同样,主题的状态变化逻辑改变时,观察者也不会受到影响。例子:为了管理一个卖厂多个分类产品,让我们建立一个销售报表系统。这个系统有以下特征:(1)用户可以选择一个他们感兴趣的分类(2)在选择了一个分类以后,需要显示下面的两种类型的报表。A、月度报表(Monthlyreport)-所选分类当月的所有交易清单。B、年度累积额(YTDsaleschart)-以月为单位显示选择分类的年度累积额图。(3)当一个不同的分类被选择时,两种报表的数据会被刷新,显示当前所选分类的报表。为了实现以上期望的功能,我们很容易的看到两个报表对象依赖于持有用户选择分类的对象。应用观察者模式于此场景,我们可以设计一个介于持有用户选择分类的对象和两个报表对象之间一个一致(同步)的交流模型。让我们定义三个类,它们的功能如表33.1所描述:Table33.1:Subject-ObserverClasses1. publicinterfaceObservable 2. publicvoidnotifyObservers(); 3. publicvoidregister(Observerobs); 4. publicvoidunRegister(Observerobs); 5. Figure33.2:ObservableInterfaceandItsImplementerReportManager类(Listing33.1)提供了声明在Observable接口中方法的实现。两个依赖于ReportManager的报表对象使用这些方法注册它们自己为观察者。ReportManager把这些注册的观察者保存到observersList矢量(vector)中。当前选择的分类构成了ReportManager对象的状态,它以实例变量的形式保存在变量department中。当为department设置一个新的值时(也就是ReportManager对象的状态改变),notifyObservers方法被调用。作为notifyObservers方法的一部分,ReportManager调用注册为观察者的refreshData(Observable)方法。Listing33.1:ReportManagerClass1. publicclassReportManagerextendsJFrame 2. implementsObservable 3. 4. 5. privateVectorobserversList; 6. privateStringdepartment; 7. publicReportManager()throwsException 8. 9. 10. observersList=newVector(); 11. 12. 13. 14. publicvoidregister(Observerobs) 15. /AddtothelistofObservers 16. observersList.addElement(obs); 17. 18. publicvoidunRegister(Observerobs) 19. /removefromthelistofObservers 20. 21. publicvoidnotifyObservers() 22. /SendnotifytoallObservers 23. for(inti=0;iobserversList.size();i+) 24. Observerobserver= 25. (Observer)observersList.elementAt(i); 26. observer.refreshData(this); 27. 28. 29. publicStringgetDepartment() 30. returndepartment; 31. 32. publicvoidsetDepartment(Stringdept) 33. department=dept; 34. 35. classButtonHandlerimplementsActionListener 36. ReportManagersubject; 37. publicvoidactionPerformed(ActionEvente) 38. if(e.getActionCommand().equals(ReportManager.EXIT) 39. System.exit(1); 40. 41. if(e.getActionCommand().equals(ReportManager.SET_OK) 42. Stringdept=(String) 43. cmbDepartmentList.getSelectedItem(); 44. /changeinstate 45. subject.setDepartment(dept); 46. subject.notifyObservers(); 47. 48. 49. publicButtonHandler() 50. 51. publicButtonHandler(ReportManagermanager) 52. subject=manager; 53. 54. 55. /endofclass 除了提供Observable接口方法的实现,ReportManager还显示了必要的用户接口,如图33.3所示,允许用户选择一个特定的、关注的分类。Figure33.3:ReportManagerUserInterface让我们定义接口Observer的两个实现:MonthlyReport和YTDChart类(如图:33.4和Listing33.2)1. publicinterfaceObserver 2. publicvoidrefreshData(Observablesubject); 3. Figure33.4:ObserverClassHierarchyListing33.2:MonthlyReportClassasanObserver1. publicclassMonthlyReportextendsJFrameimplementsObserver 2. 3. 4. privateReportManagerobjReportManager; 5. publicMonthlyReport(ReportManagerinp_objReportManager) 6. throwsException 7. super(ObserverPattern-Example); 8. objReportManager=inp_objReportManager; 9. /Createcontrols 10. 11. 12. /CreateLabels 13. 14. 15. objReportManager.register(this); 16. 17. publicvoidrefreshData(Observablesubject) 18. if(subject=objReportManager) 19. /getsubjectsstate 20. Stringdepartment=objReportManager.getDepartment(); 21. lblTransactions.setText( 22. CurrentMonthTransactions-+ 23. department); 24. VectortrnList= 25. getCurrentMonthTransactions(department); 26. Stringcontent=; 27. for(inti=0;itrnList.size();i+) 28. content=content+ 29. trnList.elementAt(i).toString()+n; 30. 31. taTransactions.setText(content); 32. 33. 34. privateVectorgetCurrentMonthTransactions(Stringdepartment 35. ) 36. Vectorv=newVector(); 37. FileUtilfutil=newFileUtil(); 38. VectorallRows=futil.fileToVector(Transactions.date); 39. /currentmonth 40. Calendarcal=Calendar.getInstance(); 41. cal.setTime(newDate(); 42. intmonth=cal.get(Calendar.MONTH)+1; 43. StringsearchStr=department+,+month+,; 44. intj=1; 45. for(inti=0;i?1) 48. StringTokenizerst= 49. newStringTokenizer(str,); 50. st.nextToken();/bypassthedepartment 51. str=+j+.+st.nextToken()+/+ 52. st.nextToken()+ 53. st.nextToken()+Items+ 54. st.nextToken()+Dollars; 55. j+; 56. v.addElement(str); 57. 58. 59. returnv; 60. 61. /endofclass ReportManager利用这个接口通知它的所有观察者。主题-观察者的关联(Subject-ObserverAssociation)通常,一个客户首先需要创建一个主题(ReportManager)实例,当一个观察者(例如:MonthlyReport,YTDChart)对象被创建。客户把主题ReportManager实例的引用传递给观察者的构造函数,观察者将自身注册到当前主题实例上。1. /ClientCode 2. publicclassSupervisorView 3. 4. 5. publicstaticvoidmain(Stringargs)throwsException 6. /CreatetheSubject 7. ReportManagerobjSubject=newReportManager(); 8. /CreateObservers 9. newMonthlyReport(objSubject); 10. newYTDChart(objSubject); 11. 12. /endofclass 类
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 智慧树知道网课《毛泽东思想和中国特色社会主义理论体系概论》课后章节测试满分答案
- 2025年中国可穿戴健身产品行业市场全景分析及前景机遇研判报告
- 2025年中国军帽行业市场全景分析及前景机遇研判报告
- 河南省周口市扶沟县包屯高级中学2025~2026学年高一上学期第一课考试政治试题(含答案)
- 水泥生产过程中工业固废的固化土改性技术
- 生物基建筑材料的使用与生态友好特性
- 地铁施工管线迁改悬吊保护方案施工效率提升
- 建军节知识竞赛题及答案
- 高科技手段在建筑材料检测中的应用与前景
- 宁波北仑区总工会招聘工会社会工作者考试真题2024
- 2016火力发电机组及蒸汽动力设备水汽质量
- 市政排水管网施工方案
- 2023年6月浙江省大学英语三级考试真题试卷
- 冶金工业矿山建设工程预算定额
- HGT-2521-2008工业硅溶胶的内容
- 译林版三年级英语上册全册课件
- 工业设计概论
- 爱是我的眼睛合唱简谱
- 如何书写护理个案
- 股骨干骨折护理查房
- 小学语文 以学生为主体的课堂学习活动设计
评论
0/150
提交评论