一. 概述
Observer 模式要解决的问题为:建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个“一”的多也能够同步改变。
Sbuject 相当于通知者,它提供依赖于它的观察者Observer 的注册(Attach)和注销(Detach)操作,并且提供了使得依赖于它的所有观察者同步的操作(Notify)。
Observer 相当于观察者,则提供一个Update操作,注意这里的 Observer 的 Update 操作并不在Observer 改变了Subject目标状态的时候就对自己进行更新,这个更新操作要延迟到 Subject 对象发出 Notify 通知所有 Observer 进行修改(调用Update)。
二. 举例
最常见的一个例子就是:对同一组数据进行统计分析时候,我们希望能够提供多种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变。
结构关系图如下:
DataSubject : 我们就认为是原始数据。
SheetObserver:就认为是表格,用来显示原始数据用的。
ChartObserver :就认为是图表,也是来显示原始数据的。
代码如下:
abstractClass.h
#ifndef ABSTRACTCLASS_H #define ABSTRACTCLASS_H #include <stdlib.h> #include <stdarg.h> typedef struct { size_t size; void* (*ctor)(void *_self, va_list *params); void* (*dtor)(void *_self); } AbstractClass; #endif
subject.h
#ifndef SUBJECT_H #define SUBJECT_H #include <stdlib.h> #include <stdarg.h> typedef struct { size_t size; void* (*ctor)(void *_self, va_list *params); void* (*dtor)(void *_self); void (*attach)(void *_self, void *_obv); // Observer void (*detach)(void *_self, void *_obv); // Observer void (*notify)(const void *_self); void (*setstate)(void *_self, char *_st); char *(*getstate)(const void *_self); } Subject; #endif
dataSubject.h
#ifndef DATASUBJECT_H #define DATASUBJECT_H typedef struct { const void *_; void *obvs; char *st; } _DataSubject; const void *DataSubject; #endif
dataSubject.c
#include "subject.h" #include "datasubject.h" #include "new.h" #include "singleList.h" #include "observer.h" #include <stdarg.h> #include <stdlib.h> #include <assert.h> static void *dataSubjectCtor(void *_self, va_list *params) { _DataSubject *self = _self; self->obvs = New(SingleList); return self; } static void *dataSubjectDtor(void *_self) { _DataSubject *self = _self; Delete(self->obvs); self->obvs = NULL; return self; } static void dataSubjectAttach(void *_self, void *_obv) { _DataSubject *self = _self; Insert(self->obvs, _obv); } static void dataSubjectDetach(void *_self, void *_obv) { _DataSubject *self = _self; Remove(self->obvs, _obv); } static void update(void *_obv, va_list *params) { Observer **obv = _obv; void *sub = va_arg(*params, void*); assert(_obv && *obv && (*obv)->update); (*obv)->update(_obv, sub); } static void dataSubjectNotify(const void *_self) { const _DataSubject *self = _self; Iterator(self->obvs, update, _self); } static void dataSubjectSetState(void *_self, char *_st) { _DataSubject *self = _self; self->st = _st; } static char *dataSubjectGetState(const void *_self) { const _DataSubject *self = _self; return self->st; } static const Subject dataSubject = { sizeof(_DataSubject), dataSubjectCtor, dataSubjectDtor, dataSubjectAttach, dataSubjectDetach, dataSubjectNotify, dataSubjectSetState, dataSubjectGetState }; const void *DataSubject = &dataSubject;
observer.h
#ifndef OBSERVER_H #define OBSERVER_H #include <stdlib.h> #include <stdarg.h> typedef struct { size_t size; void* (*ctor)(void* _self, va_list *params); void* (*dtor)(void *_self); void (*update)(void *_self, const void *sub); // Subject void (*printinfo)(const void *_self); } Observer; #endif
sheetObserver.h
#ifndef SHEETOBSERVER_H #define SHEETOBSERVER_H typedef struct { const void *_; char *st; void *sub; } _SheetObserver; const void *SheetObserver; #endif
sheetObserver.c
#include "observer.h" #include "sheetobserver.h" #include "subject.h" #include <assert.h> #include <stdio.h> #include <stdlib.h> static void* sheetObserverCtor(void *_self, va_list *params) { _SheetObserver *self = _self; self->sub = va_arg(*params, void*); const Subject **sub = self->sub; assert(self->sub && *sub && (*sub)->attach); (*sub)->attach(self->sub, _self); return self; } static void *sheetObserverDtor(void *_self) { _SheetObserver *self = _self; const Subject **sub = self->sub; assert(self->sub && *sub && (*sub)->detach); (*sub)->detach(self->sub, _self); self->sub = NULL; return self; } static void sheetObserverPrintInfo(const void *_self) { const _SheetObserver *self = _self; fprintf(stdout, "SheetObserver: %s\n", self->st); } static void sheetObserverUpdate(void *_self, const void *_sub) { _SheetObserver *self = _self; const Subject * const *sub = _sub; assert(_sub && *sub && (*sub)->getstate); self->st = (*sub)->getstate(_sub); sheetObserverPrintInfo(_self); } static const Observer _sheetObserver = { sizeof(_SheetObserver), sheetObserverCtor, sheetObserverDtor, sheetObserverUpdate, sheetObserverPrintInfo }; const void *SheetObserver = &_sheetObserver;
chatObserver.h
#ifndef CHATOBSERVER_H #define CHATOBSERVER_H typedef struct { const void *_; char *st; void *sub; } _ChatObserver; const void *ChatObserver; #endif
chatObserver.c
#include "observer.h" #include "chatobserver.h" #include "subject.h" #include <assert.h> #include <stdio.h> #include <stdlib.h> static void* chatObserverCtor(void *_self, va_list *params) { _ChatObserver *self = _self; self->sub = va_arg(*params, void*); const Subject **sub = self->sub; assert(self->sub && *sub && (*sub)->attach); (*sub)->attach(self->sub, _self); return self; } static void *chatObserverDtor(void *_self) { _ChatObserver *self = _self; const Subject **sub = self->sub; assert(self->sub && *sub && (*sub)->detach); (*sub)->detach(self->sub, _self); self->sub = NULL; return self; } static void chatObserverPrintInfo(const void *_self) { const _ChatObserver *self = _self; fprintf(stdout, "ChatObserver: %s\n", self->st); } static void chatObserverUpdate(void *_self, const void *_sub) { _ChatObserver *self = _self; const Subject * const *sub = _sub; assert(_sub && *sub && (*sub)->getstate); self->st = (*sub)->getstate(_sub); chatObserverPrintInfo(_self); } static const Observer _chatObserver = { sizeof(_ChatObserver), chatObserverCtor, chatObserverDtor, chatObserverUpdate, chatObserverPrintInfo }; const void *ChatObserver = &_chatObserver;
list.h
#ifndef LIST_H #define LIST_H #include <stdarg.h> #include <stdlib.h> typedef void (*Print_FN)(void* data); typedef void (*Handle_FN)(void *node, va_list *params); typedef struct { size_t size; void* (*ctor)(void *_self, va_list *params); void* (*dtor)(void *_self); void (*insert)(const void *_self, void *data); void (*remove)(const void *_self, void *data); void (*iterator)(const void *_self, Handle_FN handle_fn, va_list *params); void (*print)(const void *_self, Print_FN print_fn); } List; #endif
singleList.h
#ifndef SINGLELIST_H #define SINGLELIST_H typedef struct _Node { void *data; struct _Node *next; } Node; typedef struct { const void *_; Node *head; } _SingleList; extern const void *SingleList; #endif
singleList.c
#include "list.h" #include "singleList.h" #include "new.h" #include <stdlib.h> static void *singleListCtor(void *_self, va_list *params) { _SingleList *self = _self; self->head = (Node*)calloc(1, sizeof(Node)); return self; } static void *singleListDtor(void *_self) { _SingleList *self = _self; Node **p = &self->head; while ((*p) != NULL) { Node *node = *p; *p = node->next; free(node); } return self; } static void singleListInsert(const void *_self, void *data) { const _SingleList *self = _self; Node *node = (Node*)calloc(1, sizeof(Node)); Node **p = (Node **)&self->head; for (; (*p) != NULL; p = &(*p)->next) { ; } node->data = data; node->next = *p; *p = node; } static void singleListRemove(const void *_self, void *data) { const _SingleList *self = _self; Node **p = (Node **)&self->head; while ((*p) != NULL) { Node *node = *p; if (node->data == data) { *p = node->next; } else { p = &(*p)->next; } } } static void singleListIterator(const void *_self, Handle_FN handle_fn, va_list *params) { const _SingleList *self = _self; Node **p = &self->head->next; for (; (*p) != NULL; p = &(*p)->next) { va_list args; va_copy(args, *params); handle_fn((*p)->data, &args); va_end(args); } } static void singleListPrint(const void *_self, Print_FN print_fn) { const _SingleList *self = _self; Node **p = &self->head->next; while ((*p) != NULL) { print_fn((*p)->data); p = &(*p)->next; } } static const List _singleList = { sizeof(_SingleList), singleListCtor, singleListDtor, singleListInsert, singleListRemove, singleListIterator, singleListPrint, }; const void *SingleList = &_singleList;
new.h
#ifndef NEW_H #define NEW_H #include "list.h" void *New(const void *_class, ...); void Delete(void *_class); void SetState(void *_subject, char *_st); void Notify(const void *_subject); void Update(void *_observer, const void *_subject); void Insert(void *_list, void *_item); void Remove(void *_list, void *_item); void Iterator(const void *list, Handle_FN handle_fn, ...); void Print(void *_list, Print_FN print_fn); #endif
new.c
#include "new.h" #include "abstractClass.h" #include "singleList.h" #include "subject.h" #include "observer.h" #include <assert.h> void *New(const void *_class, ...) { const AbstractClass *class = _class; void *p = calloc(1, class->size); assert(p); *(const AbstractClass **)p = class; if (class->ctor) { va_list params; va_start(params, _class); p = class->ctor(p, ¶ms); va_end(params); } return p; } void Delete(void *_class) { const AbstractClass **class = _class; if (_class && *class && (*class)->dtor) { _class = (*class)->dtor(_class); } free(_class); } void SetState(void *_subject, char *_st) { Subject **subject = _subject; if (_subject && *subject && (*subject)->setstate) { (*subject)->setstate(_subject, _st); } } void Notify(const void *_subject) { const Subject * const *subject = _subject; if (_subject && *subject && (*subject)->notify) { (*subject)->notify(_subject); } } void Update(void *_observer, const void *_subject) { Observer **observer = _observer; if (_observer && *observer && (*observer)->update) { (*observer)->update(_observer, _subject); } } void Insert(void *_list, void *_item) { ((const List*)SingleList)->insert(_list, _item); } void Remove(void *_list, void *_item) { ((const List*)SingleList)->remove(_list, _item); } void Iterator(const void *_list, Handle_FN handle_fn, ...) { va_list params; va_start(params, handle_fn); ((const List*)SingleList)->iterator(_list, handle_fn, ¶ms); va_end(params); } void Print(void *_list, Print_FN print_fn) { ((const List*)SingleList)->print(_list, print_fn); }
main.c
#include "new.h" #include "datasubject.h" #include "sheetobserver.h" #include "chatobserver.h" int main(int argc, char *argv[]) { void *sub = New(DataSubject); void *o1 = New(SheetObserver, sub); void *o2 = New(ChatObserver, sub); SetState(sub, "old data"); Notify(sub); SetState(sub, "new data"); Notify(sub); Update(o1, sub); return 0; }
图片来源:http://blog.csdn.net/hmsiwtv/article/details/9626967