研磨设计模式之《观察者模式observer》

mac2022-07-05  14

概述

观察者模式主要定义对象之间的一种一对多的依赖关系,当一个对象(被观察者)的状态发生改变时,所有依赖他的对象(观察者)都得到通知并进行相应的操作;这里reader(派生自obsever)从media(派生自subject)订阅新闻,当有新闻产生时media就会调用notify通知(调用对应观察者的update方法)所有订阅该新闻的reader都拿到新闻;

1. subject 定义及实现

///< 定义 #ifndef _SUBJECT_H #define _SUBJECT_H #include "ulist.h" #include"observer.h" struct subject_vmt; struct subject { struct subject_vmt* vptr; //struct observer* observers[10]; struct list_head list_obs; void (*attach_observer)(struct subject* pthis, struct observer* pobs); void (*detach_observer)(struct subject* pthis, struct observer* pobs); void (*notify_observers)(struct subject* pthis); }; struct subject_vmt { void (*attach_observer_virtual)(struct subject* pthis, struct observer* pobs); void (*detach_observer_virtual)(struct subject* pthis, struct observer* pobs); void (*notify_observers_virtual)(struct subject* pthis); }; extern void subject_init(struct subject* pthis); #endif // _SUBJECT_H ///< 实现 #include<stdio.h> #include<stdlib.h> #include"subject.h" #include"observer.h" #include"ulist.h" void attach_observer_virtual(struct subject* pthis, struct observer* pobs) { list_add(&pobs->node, &pthis->list_obs); } void detach_observer_virtual(struct subject* pthis, struct observer* pobs) { struct observer* temp, *guard; list_for_each_entry_safe(temp, guard, &pthis->list_obs, node) { if (temp == pobs) { printf("detach a observer on observers list.\n"); list_del(&temp->node); } } } void notify_observers_virtual(struct subject* pthis) { struct observer* temp; list_for_each_entry(temp, &pthis->list_obs, node) { temp->update(temp, pthis); } } void attach_observer_subject(struct subject* pthis, struct observer* pobs) { pthis->vptr->attach_observer_virtual(pthis, pobs); } void detach_observer_subject(struct subject* pthis, struct observer* pobs) { pthis->vptr->detach_observer_virtual(pthis, pobs); } void notify_observers_subject(struct subject* pthis) { pthis->vptr->notify_observers_virtual(pthis); } void subject_init(struct subject* pthis) { static struct subject_vmt svmt = { .attach_observer_virtual = attach_observer_virtual, .detach_observer_virtual = detach_observer_virtual, .notify_observers_virtual = notify_observers_virtual, }; INIT_LIST_HEAD(&pthis->list_obs); pthis->vptr = &svmt; pthis->attach_observer = attach_observer_subject; pthis->detach_observer = detach_observer_subject; pthis->notify_observers = notify_observers_subject; } struct subject* construct_subject(void) { struct subject* pthis = malloc(sizeof(*pthis)); subject_init(pthis); return pthis; } void destruct_subject(struct subject* pthis) { free(pthis); }

2. observer 定义及实现

///< 定义 #include"ulist.h" ///< interface class struct subject; struct observer_vmt; struct observer { const struct observer_vmt* vptr; struct list_head node; void (*update)(struct observer* pthis, struct subject* psub); }; struct observer_vmt { void (*update_virtual)(struct observer* pthis, struct subject* psub); }; extern void observer_init(struct observer* pthis); #endif // _OBSERVER_H ///< 实现 #include<stdio.h> #include<stdlib.h> #include"observer.h" #include"subject.h" #include"ulist.h" void update_observer(struct observer* pthis, struct subject* psub) { pthis->vptr->update_virtual(pthis, psub); } void observer_init(struct observer* pthis) { static const struct observer_vmt ovmt = { .update_virtual = NULL, ///< must override by derived class }; INIT_LIST_HEAD(&pthis->node); pthis->vptr = &ovmt; pthis->update = update_observer; }

3. media 定义及实现

///< 定义 #ifndef _MEDIA_H #define _MEDIA_H #include"subject.h" struct media { struct subject super; char news[1024]; void (*set_news)(struct media* pthis, char* news); char* (*get_news)(struct media* pthis); }; extern struct media* construct_media(void); extern void destruct_media(struct media* pthis); #endif // _MEDIA_H ///< 实现 #include<stdio.h> #include<stdlib.h> #include<string.h> #include"observer.h" #include"subject.h" #include"media.h" static void set_news(struct media* pthis, char* news) { strncpy(pthis->news, news, 1023); struct subject* ps = (struct subject*)pthis; ps->notify_observers(ps); } static char* get_news(struct media* pthis) { return pthis->news; } void media_init(struct media* pthis) { subject_init(&pthis->super); pthis->set_news = set_news; pthis->get_news = get_news; } struct media* construct_media(void) { struct media* pthis = malloc(sizeof(*pthis)); memset(pthis, 0, sizeof(*pthis)); media_init(pthis); return pthis; } void destruct_media(struct media* pthis) { free(pthis); }

4. reader 定义及实现

///< 定义 #ifndef _READER_H #define _READER_H #include "observer.h" #include "subject.h" struct reader { struct observer super; char name[10]; void (*update)(struct observer* pthis, struct subject* psub); }; extern struct reader* construct_reader(char* name); extern void destruct_reader(struct reader* pthis); #endif // _READER_H ///< 实现 #include<stdio.h> #include<stdlib.h> #include<string.h> #include"ulist.h" #include"subject.h" #include"observer.h" #include"media.h" #include"reader.h" static void reader_update_virtual(struct observer* pthis, struct subject* psub) { struct media* pm = (struct media*)psub; printf("reader[%s] get news from media: %s\n", ((struct reader*)pthis)->name, pm->get_news(pm)); } void reader_init(struct reader* pthis, char* pname) { static struct observer_vmt rvmt = { .update_virtual = reader_update_virtual, }; observer_init(&pthis->super); pthis->super.vptr = &rvmt; pthis->update = reader_update_virtual; strncpy(pthis->name, pname, 10); } struct reader* construct_reader(char* name) { struct reader* pthis = malloc(sizeof(*pthis)); reader_init(pthis, name); return pthis; } void destruct_reader(struct reader* pthis) { free(pthis); }

5. 测试方法

#include<stdio.h> #include"subject.h" #include"observer.h" #include"media.h" #include"reader.h" int main() { struct observer* po1 = (struct observer*)construct_reader("xxdk001"); struct observer* po2 = (struct observer*)construct_reader("xxdk002"); struct observer* po3 = (struct observer*)construct_reader("xxdk003"); struct subject* ps = (struct subject*)construct_media(); ps->attach_observer(ps, po1); ps->attach_observer(ps, po2); ps->attach_observer(ps, po3); struct media* pm = (struct media*)ps; pm->set_news(pm, "hello buaa!"); ps->detach_observer(ps, po3); pm->set_news(pm, "stragetic focus!"); destruct_reader((struct reader*)po1); destruct_reader((struct reader*)po2); destruct_reader((struct reader*)po3); destruct_media(pm); }
最新回复(0)