时间:2016-12-5来源:本站原创作者:佚名

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
------分隔线----------------------------