一. 定义
观察者模式定义:当对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新,也可以称这种模式发布-订阅模式
二.应用场景
应用场景:Excel 中的数据与折线图、饼状图、柱状图之间的关系;MVC 模式中的模型与视图的关系;事件模型中的事件源与事件处理者等等
三.优缺点
主要优点有,降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系,目标与观察者之间建立了一套触发机制
当然也有缺点:当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率
所谓技术利弊两面,取决于具体应用需求
四.模式结构
观察者模式的结构如下。
结构图如下:
五.C语言实现
具体实现源码如下:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct Observer_t
{
char name[32];
bool (*adapter)(char *themeName);
bool (*update_proc)(struct Observer_t *observerObj, char *themeName);
}Observer_t;
typedef struct Subject_t
{
char name[32];
struct Observer_t *register_list[10];
bool (*add)(struct Subject_t *subjectobj, struct Observer_t * observerobj);
bool (*del)(struct Subject_t *subjectobj, struct Observer_t * observerobj);
bool (*notify)(struct Subject_t * subjectObj, char *event);
}Subject_t;
bool adapter(char *themeName)
{
if (0 == strcasecmp(themeName, "csdn-blog"))
return true;
else
return true;
}
bool update_proc(Observer_t *observerObj, char *themeName)
{
printf("[%s]收到[%s]主题跟新通知.....\n", observerObj->name, themeName);
return true;
}
bool add(Subject_t *subjectObj, Observer_t *observerObj)
{
for(int i = 0; i < (sizeof(subjectObj->register_list)/sizeof(subjectObj->register_list[0])); i++)
{
if (subjectObj->register_list[i] == NULL)
{
subjectObj->register_list[i] = observerObj;
return true;
}
}
return false;
}
bool del(Subject_t * subjectObj, Observer_t *observerObj)
{
for (int i = 0; i< (sizeof(subjectObj->register_list)/sizeof(subjectObj->register_list[0])); i++)
{
if (subjectObj->register_list[i] == observerObj)
{
subjectObj->register_list[i] = NULL;
free(observerObj);
return true;
}
}
return false;
}
bool notify(Subject_t * subjectObj, char *event)
{
for(int i = 0; i< (sizeof(subjectObj->register_list)/sizeof(subjectObj->register_list[0])); i++)
{
if (NULL == subjectObj->register_list[i])
continue;
if (subjectObj->register_list[i]->adapter(event))
subjectObj->register_list[i]->update_proc(subjectObj->register_list[i], \
subjectObj->name);
}
return true;
}
Observer_t* Observer_new(char *name)
{
Observer_t * p;
p = malloc(sizeof(*p));
if (!p)
return NULL;
memcpy(p->name, name, strlen(name));
p->adapter = adapter;
p->update_proc = update_proc;
return p;
}
Subject_t* Subject_new(char * name)
{
Subject_t * p;
p = malloc(sizeof(*p));
if (!p)
return NULL;
memset(p, 0x00, sizeof(*p));
memcpy(p->name, name, strlen(name));
p->add = add;
p->del = del;
p->notify = notify;
}
int main(void)
{
Subject_t *subject;
Observer_t *observerA;
Observer_t *observerB;
Observer_t *observerC;
printf("start to create subjecter and observer.....\n");
subject = Subject_new("creater");
observerA = Observer_new("readerA");
observerB = Observer_new("readerB");
observerC = Observer_new("readerC");
subject->add(subject, observerA);
subject->add(subject, observerB);
subject->add(subject, observerC);
subject->notify(subject, "csdn-blog");
}
六.总结
当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象有待改变的时候,应该考虑使用观察者模式,同时观察者模式所做的工作也是在解除耦合,各个对象互为工作。