1基础知识 1.1标准定义 观察者(Observer)模式标准定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 1.2分析和说明 观察者(Observer)模式属于对象行为型模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。这一模式中主要针对两个对象object和Observer。一个object可以有多个Observer,当—个object对象的状态发生改变时,所有依赖于它的Observer对象都得到通知被自动更新。 观察者(Observer)模式结构如图1所示,其角色包括抽象主题(Subject)角色、抽象观察者(Observer)角色、具体主题(ConcreteSubject)角色和具体观察者(ConcreteObserver)角色。 图1观察者模式结构 ?抽象主题(Subject)角色:主题角色把所有对观察对象的引用保存在此聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,主题角色又叫做抽象被观察者(Observable)角色,一般用一个抽象类或者一个接口实现。 ?抽象观察者(Observer)角色:为所有具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者角色一般用一个抽象类或者一个接口实现,在这个示意性的实现中,更新接口只包含一个方法(即update()方法),这个方法叫做更新方法。 ?具体主题(ConcreteSubject)角色:将有关状态存主具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者角色(ConcreteObservable)。具体主题角色负责实现对观察者引用的聚集的管理方法。 ?具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。 2应用场景举例 比如公司的通讯录是大家都要使用的,同时也是经常变化的。每次通讯录的变化,都要把这些更新后的通讯录发布给所有的公司员工。这就可以采用观察者模式。用例见图2所示。 图2观察者模式用例图 在这里可以把AbstractAddressBook抽象类理解为抽象主题(Subject)角色。AbstractEmployee抽象类是抽象观察者(Observer)角色。CompanyAddressBook类是具体主题(ConcreteSubject)角色。CompanyEmployee类是具体观察者(ConcreteObserver)角色。其结构类图如图3所示。CompanyAddressBook类继承AbstractAddressBook抽象类,CompanyEmployee类继承AbstractEmployee抽象类。AbstractEmployee抽象类关联AbstractAddressBook抽象类,即AbstractEmployee类有AbstractAddressBook类的属性。 图3观察者模式类图 观察者模式实现顺序图见图4,实现顺序描述:①基于CompanyAddressBook类创建一个addressBook对象;②基于CompanyEmployee类创建一个employee1对象;③基于CompanyEmployee类创建一个employee2对象;④调用addressBook对象的addEmployee方法,把employee1对象作为一个观察者;⑤调用addressBook对象的addEmployee方法,把employee2对象作为一个观察者;⑥addressBook对象发生变化,通知employee1对象和employee2对象这两个观察者。 图4观察者模式实现顺序图 3.Java的实现程序代码 Java程序实现主要包括AbstractAddressBook抽象类文件,AbstractEmployee抽象类文件,CompanyAddressBook类文件和CompanyEmployee类文件等4个文件。其关系如图3所示。下面分别列出这4个文件的程序代码,最后列出测试代码并显示输出结果。 AbstractAddressBook抽象类程序代码清单01所示。 程序代码清单01 publicabstractclassAbstractAddressBook{ protectedListAbstractEmployeeemployeeList=newArrayListAbstractEmployee(); protectedStringaddressBook; publicStringgetAddressBook(){returnaddressBook;} publicvoidsetAddressBook(StringaddressBook){this.addressBook=addressBook;} publicvoidaddEmployee(AbstractEmployeeemployee){employeeList.add(employee);} publicvoidremoveEmployee(AbstractEmployeeemployee){employeeList.remove(employee);} publicvoidnotice(){} } AbstractEmployee抽象类程序代码清单02所示。 程序代码清单02 publicabstractclassAbstractEmployee{ protectedAbstractAddressBookaddressBook; protectedStringaddressBookContents; publicAbstractAddressBookgetAddressBook(){returnaddressBook;} publicvoidsetAddressBook(AbstractAddressBookaddressBook){this.addressBook=addressBook;} publicvoidupdate(AbstractAddressBookbook){ setAddressBook(book); addressBookContents=addressBook.getAddressBook(); } } CompanyAddressBook继承AbstractAddressBook抽象类,其程序代码清单03所示。 程序代码清单03 publicclassCompanyAddressBookextendsAbstractAddressBook{ publicCompanyAddressBook(){ addressBook=旧的通信录; } publicvoidaddEmployee(AbstractEmployeeemployee){ //employee.setAddressBook(this); employee.update(this); super.addEmployee(employee); } publicvoidnotice(){ for(inti=0;iemployeeList.size();i++){ employeeList.get(i).update(this); } } } CompanyEmployee继承AbstractEmployee抽象类,其程序代码清单04所示。 程序代码清单04 publicclassCompanyEmployeeextendsAbstractEmployee{ privateStringemployeeName; publicStringgetEmployeeName(){returnemployeeName;} publicvoidsetEmployeeName(StringemployeeName){this.employeeName=employeeName;} publicCompanyEmployee(StringemployeeName){ super(); this.employeeName=employeeName; } publicvoidupdate(AbstractAddressBookbook){ super.update(book); System.out.println(getEmployeeName()+更新通讯录。+通讯录内容:+addressBookContents); } } 观察者模式测试程序的代码清单05如下: 程序代码清单05 publicclassClient{ publicstaticvoidmain(String[]args){ System.out.println(——————原有的通讯录——————); AbstractAddressBookaddressBook=newCompanyAddressBook(); AbstractEmployeeemployee1=newCompanyEmployee(employee1); AbstractEmployeeemployee2=newCompanyEmployee(employee2); addressBook.addEmployee(employee1); addressBook.addEmployee(employee2); System.out.println(——————更新的通讯录——————); StringnewAddressBook=新的通讯录; addressBook.setAddressBook(newAddressBook); addressBook.notice(); } } 观察者模式测试类输出结果如下所示: ——————原有的通讯录—————— employee1更新通讯录。通讯录内容:旧的通信录 employee2更新通讯录。通讯录内容:旧的通信录 ——————更新的通讯录—————— employee1更新通讯录。通讯录内容:新的通讯录 employee2更新通讯录。通讯录内容:新的通讯录 4.C#的实现程序代码 C#与java程序包括一样的接口和类。文件程序代码清单06所示。 程序代码清单06 usingSystem; usingSystem.Collections.Generic; usingSystem.Text; namespaceObserver_DesignPattern{ publicabstractclassAbstractAddressBook{ protectedListAbstractEmployeeemployeeList=newListAbstractEmployee(); protectedStringaddressBook; publicStringGetAddressBook(){returnaddressBook;} publicvoidSetAddressBook(StringaddressBook){this.addressBook=addressBook;} virtualpublicvoidAddEmployee(AbstractEmployeeemployee){ employeeList.Add(employee); } virtualpublicvoidRemoveEmployee(AbstractEmployeeemployee){ employeeList.Remove(employee); } abstractpublicvoidNotice(); } publicabstractclassAbstractEmployee{ protectedAbstractAddressBookaddressBook; protectedStringaddressBookContents; publicAbstractEmployee(StringemployeeName){} publicAbstractAddressBookGetAddressBook(){returnaddressBook;} publicvoidSetAddressBook(AbstractAddressBookaddressBook){ this.addressBook=addressBook; } virtualpublicvoidUpdate(AbstractAddressBookbook){ SetAddressBook(book); addressBookContents=addressBook.GetAddressBook(); } } publicclassCompanyAddressBook:AbstractAddressBook{ publicCompanyAddressBook(){addressBook=旧的通信录;} overridepublicvoidAddEmployee(AbstractEmployeeemployee){ employee.Update(this); base.AddEmployee(employee); } overridepublicvoidNotice(){ for(inti=0;iemployeeList.Count;i++){employeeList[i].Update(this);} } } publicclassCompanyEmployee:AbstractEmployee{ privateStringemployeeName; publicStringEmployeeName{ get{returnemployeeName;} set{employeeName=value;} } publicCompanyEmployee(StringemployeeName):base(employeeName){ this.employeeName=employeeName; } overridepublicvoidUpdate(AbstractAddressBookbook){ base.Update(book); Console.WriteLine(EmployeeName+更新通讯录。+通讯录内容:+addressBookContents); } } } 观察者模式测试程序的代码清单07如下: 程序代码清单07 classObserver_DesignPattern{ staticvoidMain(string[]args){ Console.WriteLine(——————原有的通讯录——————); AbstractAddressBookaddressBook=newCompanyAddressBook(); AbstractEmployeeemployee1=newCompanyEmployee(employee1); AbstractEmployeeemployee2=newCompanyEmployee(employee2); addressBook.AddEmployee(employee1); addressBook.AddEmployee(employee2); Console.WriteLine(——————更新的通讯录——————); StringnewAddressBook=新的通讯录; addressBook.SetAddressBook(newAddressBook); addressBook.Notice(); } } 观察者模式测试类输出结果如下所示: ——————原有的通讯录—————— employee1更新通讯录。通讯录内容:旧的通信录 employee2更新通讯录。通讯录内容:旧的通信录 ——————更新的通讯录—————— employee1更新通讯录。通讯录内容:新的通讯录 employee2更新通讯录。通讯录内容:新的通讯录 5.C++的程序实现代码 由于C++语言稍微不同于java和C#语言。需要首先定义头文件,然后再是程序文件,同时,由于本程序调用了MFC,所以我们在头文件中要引用MFC,如#includestdafx.h等。在定义过程中,VC并不是完全的面向对象的语言,故采用一些C++类来定义接口,主要区别是这些C++类的方法都是虚拟方法。这是C++语言与java和C#语言相差比较大的地方。 C++程序实现主要包括AddressBook抽象类文件,Employee抽象类文件,CompanyAddressBook类和CompanyEmployee类等4个文件。其关系如图3所示。下面分别列出这4个文件的程序代码,最后列出测试代码并显示输出结果。 AddressBook抽象类文件和CompanyAddressBook类的头文件代码清单08所示。 程序代码清单08 classEmployee; classAddressBook{ public: CStringgetAddressBook(); voidsetAddressBook(CStringaddressBook); voidaddEmployee(Employee*employee); voidremoveEmployee(Employee*employee); virtualvoidnotice()=0; protected: CListEmployee*,Employee*EmployeeList; CStringaddressBook; }; classCompanyAddressBook:publicAddressBook{//定义观察者类 public: CompanyAddressBook(); voidaddEmployee(Employee*employee); voidnotice(); }; AddressBook抽象类文件和CompanyAddressBook类的程序实现代码清单09所示。 程序代码清单09 CStringAddressBook::getAddressBook(){returnaddressBook;} voidAddressBook::setAddressBook(CStringbook){addressBook=book;} voidAddressBook::addEmployee(Employee*employee){EmployeeList.AddTail(employee);} voidAddressBook::removeEmployee(Employee*employee){ POSITIONpos=EmployeeList.Find(employee); EmployeeList.RemoveAt(pos); } voidAddressBook::notice(){} CompanyAddressBook::CompanyAddressBook(){addressBook=旧的通信录;} voidCompanyAddressBook::addEmployee(Employee*employee){ employee-update(this); AddressBook::addEmployee(employee); } voidCompanyAddressBook::notice(){ POSITIONpos; for(pos=EmployeeList.GetHeadPosition();pos;EmployeeList.GetNext(pos)){ EmployeeList.GetAt(pos)-update(this); } } Employee抽象类文件和CompanyEmployee类的头文件代码清单10所示。 程序代码清单10 classEmployee{//定义Employee祖先类 public: AddressBook*getAddressBook(); voidsetAddressBook(AddressBook*addressBook); virtualvoidupdate(AddressBook*book)=0; protected: AddressBook*addressBook; CStringaddressBookContents; }; classCompanyEmployee:publicEmployee{//定义CompanyEmployee实现类 public: CompanyEmployee(CStringname); CStringgetEmployeeName(); voidsetEmployeeName(CStringname); voidupdate(AddressBook*book); private: CStringemployeeName; }; Employee抽象类文件和CompanyEmployee类的程序实现代码清单11所示。 程序代码清单11 AddressBook*Employee::getAddressBook(){returnaddressBook;} voidEmployee::setAddressBook(AddressBook*book){addressBook=book;} voidEmployee::update(AddressBook*book){ setAddressBook(book); addressBookContents=addressBook-getAddressBook(); //printf(Employee更新通讯录。\n); } CompanyEmployee::CompanyEmployee(CStringname){employeeName=name;} CStringCompanyEmployee::getEmployeeName(){returnemployeeName;} voidCompanyEmployee::setEmployeeName(CStringname){employeeName=name;} voidCompanyEmployee::update(AddressBook*book){ setAddressBook(book); addressBookContents=addressBook-getAddressBook(); printf(getEmployeeName()+更新通讯录。+通讯录内容:+addressBookContents+\n); } 观察者模式测试程序的代码清单12所示。其实现的序列图如图05所示。 代码清单12 #includestdafx.h #includeEmployee.h #includeAddressBook.h intmain(intargc,char*argv[]){ printf(——————原有的通讯录——————\n); AddressBook*addressBook=newCompanyAddressBook(); Employee*employee1=newCompanyEmployee(employee1); Employee*employee2=newCompanyEmployee(employee2); addressBook-addEmployee(employee1); addressBook-addEmployee(employee2); addressBook-notice(); printf(——————更新的通讯录——————\n); CStringnewAddressBook=新的通讯录; addressBook-setAddressBook(newAddressBook); addressBook-notice(); deleteemployee1,employee2,addressBook; return0; } 观察者模式测试类输出结果如下所示: ——————原有的通讯录—————— employee1更新通讯录。通讯录内容:旧的通信录 employee2更新通讯录。通讯录内容:旧的通信录 ——————更新的通讯录—————— employee1更新通讯录。通讯录内容:新的通讯录 employee2更新通讯录。通讯录内容:新的通讯录 6扩展和说明 在java语言中已经实现了Observer设计模式。JDK里提供的Observer设计模式的实现由java.util.Observable类和java.util.Observer接口组成。java.util.Observer是观察者角色,java.util.Observable是被观察目标角色,对应于Subject角色。 Observer是一个接口,它里面只定义了一个方法:publicvoidupdate(Observableobs,Objectobj)在用户实现的这个方法中,可以只对obs的某些事件进行响应,也可以通过调用getXXX()来得到obs最新的状态。上述例子的java程序可以由Employee类、AddressBook类、Client类等三个文件实现。 AddressBook类源程序见程序清单08。 程序代码清单08 importjava.util.Observable; publicclassAddressBookextendsObservable{ protectedStringaddressBookContent; publicAddressBook(){super();} publicStringgetAddressBook(){returnaddressBookContent; publicvoidsetAddressBook(StringaddressBook){this.addressBookContent=addressBook;} publicvoidaddEmployee(Employeeemployee){super.addObserver(employee);} publicvoidremoveEmployee(Employeeemployee){deleteObserver(employee); publicvoidmodifyAddress(StringaddressBook){ setAddressBook(addressBook); setChanged(); notifyObservers(addressBook); } } Employee.类源程序见程序清单09。 程序代码清单08 importjava.util.Observable; importjava.util.Observer; publicclassEmployeeimplementsObserver{ protectedStringaddressBookContents; privateStringemployeeName; publicEmployee(StringemployeeName){setEmployeeName(employeeName);} publicStringgetEmployeeName(){returnemployeeName;} publicvoidsetEmployeeName(StringemployeeName){this.employeeName=employeeName;} publicStringgetAddressBookContents(){returnaddressBookContents;} publicvoidsetAddressBookContents(StringaddressBookContents){ this.addressBookContents=addressBookContents; } publicvoidupdate(Observableobject,Objectarg){ if(arginstanceofString){ setAddressBookContents(arg.toString()); System.out.println(getEmployeeName()+获得通信录:+getAddressBookContents()); } } } Client类源程序见程序清单10。 程序代码清单10 publicclassClient{ publicstaticvoidmain(String[]args){ System.out.println(——————原有的通讯录——————); AddressBookaddressBook=newAddressBook(); Employeeemployee1=newEmployee(employee1); Employeeemployee2=newEmployee(employee2); Employeeemployee3=newEmployee(employee3); addressBook.addEmployee(employee1); addressBook.addEmployee(employee2); addressBook.addEmployee(employee3); addressBook.modifyAddress(旧的通讯录); System.out.println(——————更新的通讯录——————); StringnewAddressBook=新的通讯录; addressBook.modifyAddress(newAddressBook); } } 参考文献 [1]E.Gamma,R.Helm,R.Johnson,andVlissides.DesignPatternsElementsofReusableObjectOrientedSoftware.Addison-Wesley, [2]E.Gamma,R.Helm,R.Johnson,andVlissides.著,李英军等译,设计模式:可复用面向对象软件的基础,北京:机械工业出版社..9. [3]阎宏,Java与模式,北京:电子工业出版社..10 [4]王俊峰戚晓滨.设计模式和UML.计算机应用研究,.16(5),27-29,39. [5]陈琴朱正强.UML在设计模式描述中的应用.计算机工程与设计,.24(4),81-84. [6]吴信永宋东刘飞.基于构件技术的通用ATS框架设计.计算机测量与控制,.16(2),-,. [7]赵德新刘瑾.设计模式思想及其应用.天津理工大学学报,.23(5),58-61. [8]阎小涛刘涛沈为群.设计模式在航空发动机试验台测控系统中的应用.兵工自动化,.26(10),62-64. [9]张光会闫新庆.Java2中Observer模式探究.南阳师范学院学报,.1(6),80-82,92. [10]张宁王越王东.观察者模式及其在软件开发中的应用.大众科技,.(11),35-36. [11]吴善明沈建京刘辉.浅析Observer模式在GIS软件设计中的应用.计算机工程与设计,.28(18),-. [12]董荣辉丁政建曾天慧.GoF23中Observer设计模式的AOP实现与OOP实现的对比.微计算机信息,.(05X),-,. [13]王雪涛樊银亭.Observer模式在.net架构中的应用研究.华北水利水电学院学报,.29(4),79-81,84. [14]雷镇雷蕾周淑秋王华.Observer模式在JavaGUI中的分析与应用.计算机系统应用,.(5),32-34. [15]王江涛.观察者设计模式在嵌入式系统中的应用.计算机工程,.30(B12),66-68,. [16]张晓东闫新庆等.Observer软件设计模式在Delphi中的实现.河南师范大学学报:自然科学版,.29(4),85-87. [17]周传宏吴思达.可扩展的基于设计模式的PLM定制架构.制造业自动化,.29(4),27-29,76. [18]杨洲王自强周余都思丹.设计模式在数据采集系统中的应用.微电子学与计算机,.25(2),-. [19]赵永明郭敏.设计模式在雷达终端软件系统中的应用.火控雷达技术,.(2),93-96. [20]王晓波蔡汉明王军崔慧敏.设计模式在线切割CAD软件开发中的应用.机电工程技术,.35(2),44-47. [21]万波张焰罗治强.设计模式在Drawcli程序中的应用.计算机应用与软件,.20(8),12-13,84. [22]李长春廖建新王纯朱晓民.软件界面国际化及设计模式的应用.北京工商大学学报:自然科学版,.25(5),53-56. [23]唐露萍陈洁.设计模式在短波通信软件中的应用.计算机工程,.34(D09),-. [24]何剑峰雷金辉高润琴.设计模式在真空炉控制系统中的应用.工业控制计算机,.21(3),42-42,45. [25]张晓怀陈业初寇蔚.设计模式在设备故障红外智能诊断软件中的应用.机电设备,.24(11),29-33,13. [26]洪中.组态软件设计中的模式应用.微计算机信息,.(28),-. [27]肖保良宋东赵胜.基于模式的ATS领域框架研究.计算机测量与控制,.15(9),-. [28]曹恒凌正阳蒋知峰王剑兰.软件设计模式在数控系统人机界面开发中的应用.华东理工大学学报:社会科学版,.33(6),-. [29]何江玲孙其博.设计模式在软交换软件系统中的应用.世界电信,.16(9),42-44. [30]肖志峰龚健雅王艳东翟晓芳.面向对象的软件设计模式在配电GIS中的应用.测绘信息与工程,.30(3),3-5. [31]袁杲杨玲.Observer与Command模式在VTK类库设计中的应用研究.西南民族大学学报:自然科学版,.33(4),-. [32]戴建国郭理曹传东.JUnit框架剖析.计算机与数字工程,.36(8),43-45,. [33]肖计划刘海砚张吉才.设计模式在地图制图软件开发中的应用.测绘工程,.17(5),4-7,11. [34]聂颖.设计模式在图形处理软件中的应用.计算机应用,.24(B12),-. [35]饶一梅王治宝.软件设计模式及其在Java类库中的典型实现.计算机工程与应用,.38(4),48-50. 北京有哪些医院治疗白癜风治疗白癜风应到北京那家治最好转载请注明原文网址:http://www.helimiaopu.com/cxfz/cxfz/2529.html |