概述
观察者模式主要定义对象之间的一种一对多的依赖关系,当一个对象(被观察者)的状态发生改变时,所有依赖他的对象(观察者)都得到通知并进行相应的操作;这里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 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
#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"
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
#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,
};
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
#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
#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
);
}
转载请注明原文地址: https://mac.8miu.com/read-415037.html