- 定义
观察者是一种行为设计模式,允许你定义一种订阅机制,可在对象事件发生时通知多个“观察”该对象的其他对象。
假如你有两种类型的对象: 顾客 和 商店 。顾客对某个特定品牌的产品非常感兴趣(例如最新型号的 iPhone 手机),而该产品很快将会在商店里出售。顾客可以每天来商店看看产品是否到货。但如果商品尚未到货时,绝大多数来到商店的顾客都会空手而归。
另一方面,每次新产品到货时,商店可以向所有顾客发送邮件(可能会被视为垃圾邮件)。这样,部分顾客就无需反复前往商店了,但也可能会惹恼对新产品没有兴趣的其他顾客。我们似乎遇到了一个矛盾:要么让顾客浪费时间检查产品是否到货,要么让商店浪费资源去通知没有需求的顾客。
拥有一些值得关注的状态的对象通常被称为目标,由于它要将自身的状态改变通知给其他对象,我们也将其称为发布者(publisher)。
所有希望关注发布者状态变化的其他对象被称为订阅者(subscribers)。
观察者模式建议你为发布者类添加订阅机制,让每个对象都能订阅或取消订阅发布者事件流。不要害怕!这并不像听上去那么复杂。实际上,该机制包括:
1)一个用于存储订阅者对象引用的列表成员变量;
2)几个用于添加或删除该列表中订阅者的公有方法。
- 代码实现
#ifndef _OBSERVER_H_
#define _OBSERVER_H_
typedef struct
{
void (*update_Audio_date)(int *audio_buf);
}interfaces_update_Audio_t;
typedef struct
{
void (*update_video_date)(int *video_buf);
}interfaces_update_Video_t;
#endif
#include "stdio.h"
#include "string.h"
#include <stdint.h>
#include "Observer.h"
#define OBSERVER_MAX_COUNT 10
Observer Audio_Observer;
Observer Video_Observer;
typedef struct observer
{
void (*update)(int *buf);
}Observer;
typedef struct subject
{
Observer *array_observer[OBSERVER_MAX_COUNT];
int (*register_observer)(Observer *observer);
int (*remove_observer)(Observer *observer);
void (*notify_observer)(int *buf);
//void (*other_function)(void);
}Subject;
Subject SwitchBot_Subject;
static int observer_count=0;
void update_video_date(int *buf)
{
//do video function
}
void update_audio_date(int *buf)
{
//do audio fuction
}
int woan_register_observer(Observer *observer)
{
if(observer_count>=OBSERVER_MAX_COUNT)
return 0;
SwitchBot_Subject.array_observer[observer_count++]=observer;
return 1;
}
int woan_remove_observer(Observer *observer)
{
int i=0;
for(i=0;i<observer_count;i++)
{
if(observer==SwitchBot_Subject.array_observer[i])
{
SwitchBot_Subject.array_observer[i]=0;
break;
}
}
return 1;
}
void woan_notify_observer(int *buf)
{
int i=0;
Observer *observer=0;
for(i=0;i<observer_count;i++)
{
observer=SwitchBot_Subject.array_observer[i];
if(observer!=0)
observer->update(buf);
}
}
void init_switchbot_subject()
{
int i=0;
for(i=0;i<OBSERVER_MAX_COUNT;i++)
SwitchBot_Subject.array_observer[i]=0;
SwitchBot_Subject.notify_observer=woan_notify_observer;
SwitchBot_Subject.remove_observer=woan_remove_observer;
SwitchBot_Subject.register_observer=woan_notify_observer;
}
uint8_t get_date(int *buf)
{
//buf get something
}
void check_and_notify()
{
int *buf;
int state=0;
get_date(buf);
if(buf[0] == 0x570f0201)
SwitchBot_Subject.notify_observer(buf);
}
void init_observer(Observer *observer,void (*update)(void))
{
observer->update=update;
}
void add_observer(Subject *subject,Observer *observer)
{
subject->register_observer(observer);
}
void main()
{
interfaces_update_Audio_t *audio_func;
interfaces_update_Video_t *video_func;
init_switchbot_subject();
init_observer(&Audio_Observer,audio_func->update_Audio_date);
init_observer(&Video_Observer,video_func->update_video_date);
init_observer(&Video_Observer,video_func->update_video_date);
add_observer(&SwitchBot_Subject,&Audio_Observer);
add_observer(&SwitchBot_Subject,&Video_Observer);
while(1)
{
check_and_notify();
}
}
- 观察者适用场景:
当一个对象状态的改变需要改变其他对象,或实际对象是事
先未知的或动态变化的时,可使用观察者模式。
当应用中的一些对象必须观察其他对象时,可使用该模式。
但仅能在有限时间内或特定情况下使用。
- 优缺点:
开闭原则。 你无需修改发布者代码就能引入新的订阅者类(如果是发布者接口则可轻松引入发布者类)。
你可以在运行时建立对象之间的联系。
订阅者的通知顺序不是随机的