1、定义
观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生变化时,会自动通知所有观察者对象进行更新操作。观察者模式也被称为发布-订阅(Publish-Subscribe)模式。
在观察者模式中,有两个核心角色:主题(Subject)和观察者(Observer)。主题维护一个观察者列表,并提供了注册、删除、通知观察者等接口;而观察者则通过实现更新(Update)接口来接收主题的通知并进行相应的处理。
2、原理
观察者模式的原理是通过使用面向对象的编程思想,将观察者与主题解耦,使得它们之间的依赖关系更加灵活。主题只需要维护一个观察者列表,并提供通知观察者的接口即可,而观察者则可以根据需要随时注册或取消注册对主题的监听。当主题状态发生变化时,主题会自动调用所有观察者的更新接口,从而实现了观察者模式的功能。
3、适用场景
观察者模式适用于以下场景:
-
当一个对象的改变需要同时改变其他对象的时候,可以使用观察者模式。例如,在一个图形界面程序中,当用户修改某个控件的值时,需要更新其他相关的控件。
-
当一个对象的改变需要通知其他多个对象,并且这些对象之间没有紧密耦合关系的时候,可以使用观察者模式。例如,在一个游戏中,当玩家得分发生变化时,需要通知所有其他玩家进行更新。
-
当一个对象的改变需要触发一系列连锁反应的时候,可以使用观察者模式。例如,在一个企业系统中,当某个员工的信息发生变化时,需要自动更新其所属部门、岗位等相关信息。
总之,观察者模式可以帮助我们更好地管理对象之间的依赖关系,实现松耦合的设计,提高代码的可维护性和可扩展性。
4、示例
下面是一个简单的观察者模式的示例代码:
#include <stdio.h>
#include <stdlib.h>
#define MAX_OBSERVERS 10
typedef struct observer_t observer_t;
typedef struct subject_t subject_t;
struct observer_t {
void (*update)(observer_t*, int);
};
struct subject_t {
observer_t* observers[MAX_OBSERVERS];
int num_observers;
int state;
};
void register_observer(subject_t* subject, observer_t* observer) {
if (subject->num_observers < MAX_OBSERVERS) {
subject->observers[subject->num_observers++] = observer;
}
}
void notify_observers(subject_t* subject) {
for (int i = 0; i < subject->num_observers; i++) {
observer_t* observer = subject->observers[i];
observer->update(observer, subject->state);
}
}
void set_state(subject_t* subject, int state) {
subject->state = state;
notify_observers(subject);
}
void update(observer_t* observer, int state) {
printf("Observer %p received update: %d\n", observer, state);
}
int main() {
subject_t subject;
observer_t observer1 = { .update = update };
observer_t observer2 = { .update = update };
register_observer(&subject, &observer1);
register_observer(&subject, &observer2);
set_state(&subject, 42);
return 0;
}
这个示例代码中,我们定义了两个结构体:observer_t
表示观察者,subject_t
表示主题。每个观察者都有一个update
函数,当主题的状态发生变化时,会调用所有观察者的update
函数。主题可以通过register_observer
函数注册观察者,并通过set_state
函数设置自己的状态并通知所有观察者。
在main
函数中,我们创建了一个主题对象和两个观察者对象,并将观察者对象注册到主题对象中。然后我们设置主题对象的状态为42,这将导致所有观察者对象的update
函数被调用,并输出相应的消息。
要编译这个示例代码,可以使用以下命令:
gcc -o observer observer.c
运行程序:
./observer
输出:
Observer 0x7ffd18df31b8 received update: 42
Observer 0x7ffd18df31c0 received update: 42
说明两个观察者都成功接收到了主题对象的状态更新通知。