c语言设计模式代码完整实现-观察者模式(Observer)

 

模式介绍:观察者模式(Observer)

              观察者模式定义了对象之间的一对多依赖关系,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并且自动更新。在这里,发生改变的对象称之为观察目标,而被通知的对象称之为观察者。一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,所以么可以根据需要增加和删除观察者,使得系统更易于扩展。

图表 1观察者模式流程图

观察者模式在C语言里也是实现形式非常明显的模式。逻辑上和责任链模式最相近的一个设计模式为观察者模式。观察者模式和责任链模式的最大的差别在于,事件会被通知到每一个handler,而不是逐级处理。也不存在优先级的说法,也不会出现事件没有处理需要异常函数收尾。一个Observer是否注册和执行不应该影响其他的Observer。而在责任链模式上,前面的责任handler在传递给下一个handler时,是可以改变事件相关变量。

              但是在C语言实现上,观察者模式的handler绝大部分也是按照链表来组织的,在代码执行上,实际上相当于遍历链表。和责任链模式的区别在于每个handler没有优先级,没有权力决定是否停止遍历,最后事件也不需要被handler消费掉,也就是没有异常函数。

          所以从C语言代码实现上讲,观察者模式可以看作责任链模式的特例。

1. 无优先级

2. 不能修改随事件而来的变量。比如在netfilter使用责任链模式就修改了随事件而来的数据包。

3. 每个handler/observer只能无条件把事件传给observer链表的下一个节点。

图表 2观察者模式和责任链模式对比

左边是责任链模式,右边是观察者模式的内核代码实现流程。

观察者模式实现

观察者节点定义

注册和反注册函数

调用流程

内核的观察者模式实现

观察节点模型

事件触发的处理函数

 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

#include "list.h"

/*
	观察者模式定义了对象之间的一对多依赖关系,这样一来,当一个对象改变状态时,
	它的所有依赖者都会收到通知并且自动更新。
	在这里,发生改变的对象称之为观察目标,而被通知的对象称之为观察者。
	一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,
	所以么可以根据需要增加和删除观察者,使得系统更易于扩展。
	观察者模式在C语言里也是实现形式非常明显的模式。
	观察者模式与责任链模式的区别:
	逻辑上和责任链模式最相近的一个设计模式为观察者模式。
	观察者模式和责任链模式的最大的差别在于,事件会被通知到每一个handler,而不是逐级处理。
	也不存在优先级的说法,也不会出现事件没有处理需要异常函数收尾。
	一个Observer是否注册和执行不应该影响其他的Observer。
	而在责任链模式上,前面的责任handler在传递给下一个handler时,是可以改变事件相关变量。
	但是在C语言实现上,观察者模式的handler绝大部分也是按照链表来组织的,
	在代码执行上,实际上相当于遍历链表。和责任链模式的区别在于每个handler没有优先级,
	没有权力决定是否停止遍历,最后事件也不需要被handler消费掉,也就是没有异常函数。
	所以从C语言代码实现上讲,观察者模式可以看作责任链模式的特例。
	1. 无优先级
	2. 不能修改随事件而来的变量。比如在netfilter使用责任链模式就修改了随事件而来的数据包。
	3. 每个handler/observer只能无条件把事件传给observer链表的下一个节点。
*/

typedef int(*observer_func)(char* buf);

struct observer_ops_node
{
    struct list_head list; //内核链表标准结构
    observer_func handler; //handler的回调函数,没有优先级
};

//全局的观察者链
struct list_head observer_global_list;
//具体的处理函数
int observer_handler1(char*buf)
{
    //do something
    printf("observer handler1.\n");
    return 0;
}

int observer_handler2(char* buf)
{
    //do something
    printf("observer handler2.\n");
    return 0;
}

struct observer_ops_node node1;
struct observer_ops_node node2;

void observer_mode_init()
{
    node1.handler = observer_handler1;
    node2.handler = observer_handler2;
    init_list_head(&observer_global_list);
}

//register and unregister function
/*
特别注意,一般是需要信号量锁定的,
因为很可能链条上的函数正在执行。
内核里喜欢用 rcu 锁,可以避免资源互斥引起cpu浪费。
*/

int observer_register(struct observer_ops_node* node)
{
    //lock observer_global_list
    //add node into observer_global_list
    //unlock observer_global_list
    list_add_tail(&node->list, &observer_global_list);
    printf("register observer\n");
    return 0;
}

int observer_unregister(struct observer_ops_node* node)
{
    //lock observer_global_list
    //delete node into observer_global_list
    //unlock observer_global_list
    list_del(&node->list);
    printf("unregister observer.\n");
    return 0;
}

/*不检查观察者结果,必须全部遍历完*/
int main()
{
    struct list_head*node;
    struct observer_ops_node* node_entry;
    char buf[16];

    observer_mode_init();
    observer_register(&node1);
    observer_register(&node2);
    /*这里的意思是,如果观察的目标的状态等发生变化了,这个目标对象可以是某个数据的变化,
    例如系统中增加了一条学生的信息,
    那么就依次通知给各个观察者
    */
    //something happened,loop list
    LIST_FOR_EACH(node, &observer_global_list)
    {
        node_entry = list_entry(node,struct observer_ops_node, list);
        //依次通知给观察者//
        /*
        观察者的一个Observer是否注册和执行不应该影响其他的Observer。
        而在责任链模式上,前面的责任handler在传递给下一个handler时,是可以改变事件相关变量。
        */
        node_entry->handler(buf);
    }
    getchar();
    return 0;
}

 

 

模式实现总结

              总体用法和责任链模式类似,而在内核里实现的观察者模式其实并没有那么“纯粹”,而是扩展了优先级特性和可停止特性。这个破坏了Observer之间的独立性,因为原则上,一个Observer是否注册和执行不应该影响其他的Observer,内核的扩展这就使观察者模式变成了责任链模式模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值