意图:
一个对象(subject)的状态发生了变化,可以通知与之关联的对象(observer)自动进行相应的更新。定义了对象之间的一对多的关系。
依赖模式,发布-订阅模式
数据对象(subject)
图形用户界面(observer)
数据有许多中显示方式,如表格,柱状图,饼状图等。当数据的内容发生变化时,与之对应的表格,柱状图,饼状图也要发生相应的变化。
应用:
smalltalk的MVC模型中。
举例:
在一个公文处理系统中,开发者定义了一个公文结构OfficeDoc,其中定义了公文应该具有的属性。当公文类得内容或状态发生变化时,与之相关联的DocExplorer结构的值都需要发生相应的改变。一个OfficeDoc结构能够关联一组DocExplorer结构。当OfficeDoc结构的内容发生改变,所有与之关联的DocExplorer都将被更新。
代码:
#include <stdio.h>
#define OBS_MAXNUM 20
typedef void ( *func ) ( struct OfficeDoc * ,struct DocExplorer * );
struct DocExplorer{
func update;
int data;
};
struct OfficeDoc{
DocExplorer * myObs[ OBS_MAXNUM ];
int index;
int data;
};
void attach( OfficeDoc * doc, DocExplorer * ob ){
int loop=0;
if( doc->index >= OBS_MAXNUM || ob == NULL) return; //函数非法输入处理
for( loop =0; loop < doc->index ; loop++)
if( doc->myObs[loop] == ob ) return;
doc->myObs[doc->index] = ob;
doc->index++;
};
void detach( OfficeDoc * doc, DocExplorer * ob ){
int loop=0;
if( ob == NULL ) return;
for( loop=0; loop < doc->index; loop++){
if( doc->myObs[ loop ] == ob ) {
if( loop <= doc->index-2 )
doc->myObs[loop] = doc->myObs[doc->index -1];
doc->myObs[doc->index-1] = NULL;
doc->index--;
break;
}
}
}
void update1( OfficeDoc * doc, DocExplorer * ob){
ob->data = doc->data;
}
void update2( OfficeDoc * doc, DocExplorer * ob){
ob->data = 2*doc->data;
}
void notifyObs( OfficeDoc * doc ){
for( int loop=0; loop<doc->index; loop++){
doc->myObs[loop]->update( doc, doc->myObs[loop] );
}
}
int main(){
struct OfficeDoc doc;
doc.index = 0;
struct DocExplorer ob1;
ob1.data =0;
struct DocExplorer ob2;
ob2.data = 0;
ob1.update = update1;
ob2.update = update2;
attach( &doc, &ob1);
attach( &doc, &ob2);
scanf( "%d", &doc.data);
notifyObs( &doc );
printf( "the ob1's data is %d\n", ob1.data);
printf( "the ob2's data is %d\n", ob2.data);
return 0;
}