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

概述

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

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);
}
发布了134 篇原创文章 · 获赞 20 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/u011583798/article/details/102243207