通过C语言实现#软件设计模式#观察者模式

一. 定义

观察者模式定义:当对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新,也可以称这种模式发布-订阅模式

二.应用场景

应用场景:Excel 中的数据与折线图、饼状图、柱状图之间的关系;MVC 模式中的模型与视图的关系;事件模型中的事件源与事件处理者等等

三.优缺点

主要优点有,降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系,目标与观察者之间建立了一套触发机制
当然也有缺点:当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率
所谓技术利弊两面,取决于具体应用需求

四.模式结构

观察者模式的结构如下。

  1. 抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的集合和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。

  2. 抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用

结构图如下:
在这里插入图片描述

五.C语言实现

具体实现源码如下:源码github获取

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

/**
 * @brief 观察者抽象类
 * @note adapter 适配接口,适配主题 update_proc 更新处理接口
 */
typedef struct Observer_t
{
    char name[32];
    bool (*adapter)(char *themeName);
    bool (*update_proc)(struct Observer_t *observerObj, char *themeName);
}Observer_t;

/**
 * @brief 主题抽象类
 * @note register_list 观察者列表 add 观察者注册接口 del 注销观察者接口
 * @note notify 通知观察者接口,这里可以实现为同步或者异步通知
 */
typedef struct Subject_t
{
    char name[32];
    struct Observer_t *register_list[10];
    bool (*add)(struct Subject_t *subjectobj, struct Observer_t * observerobj);
    bool (*del)(struct Subject_t *subjectobj, struct Observer_t * observerobj);
    bool (*notify)(struct Subject_t * subjectObj, char *event);
}Subject_t;

/**
 * @brief adapter
 * @param themeName 主题名
 * @return true适配成功 otherwise false 适配失败
 * @note 对主题过滤,对适配的主题进行通知
 */
bool adapter(char *themeName)
{
    if (0 == strcasecmp(themeName, "csdn-blog"))
        return true;
    else
        return true;
}

/**
 * @brief update_proc
 * @param observerObj 观察者 themeName 主题
 * @return true
 * @note 更新主题,或者处理对应事件
 */
bool update_proc(Observer_t *observerObj, char *themeName)
{
    printf("[%s]收到[%s]主题跟新通知.....\n",        observerObj->name, themeName);

    return true;
}

/**
 * @brief add
 * @param subjectObj 主题对象
 * @param observerObj 观察者对象
 * @return true 注册进观察者列表成功,else false 注册失败
 * @note 观察者对象注册
 */
bool add(Subject_t *subjectObj, Observer_t *observerObj)
{
    
    for(int i = 0; i < (sizeof(subjectObj->register_list)/sizeof(subjectObj->register_list[0])); i++)
    {
        if (subjectObj->register_list[i] == NULL)
        {
            subjectObj->register_list[i] = observerObj;
            return true;
        }
    }
    
    return false;
}

/**
 * @brief del
 * @param subjectObj 主题对象
 * @param observerObj 观察者对象
 * @return true 注销进观察者列表成功,else false 注册失败
 * @note 观察者对象注销
 */
bool del(Subject_t * subjectObj, Observer_t *observerObj)
{
    for (int i = 0; i< (sizeof(subjectObj->register_list)/sizeof(subjectObj->register_list[0])); i++)
    {
        if (subjectObj->register_list[i] == observerObj)
        {
            subjectObj->register_list[i] = NULL;
            free(observerObj);
            return true;
        }
    }
    
    return false;
}

/**
 * @brief notify
 * @param subjectObj 主题对象
 * @param event 通知事件
 * @return true
 * @note 通知到所有观察者
 */
bool notify(Subject_t * subjectObj, char *event)
{
    for(int i = 0; i< (sizeof(subjectObj->register_list)/sizeof(subjectObj->register_list[0])); i++)
    {
        if (NULL == subjectObj->register_list[i])
            continue;
        
        if (subjectObj->register_list[i]->adapter(event))
            subjectObj->register_list[i]->update_proc(subjectObj->register_list[i], \
                                                      subjectObj->name);
    }
    
    return true;
}

/**
 * @brief Observer_new
 * @param name 对象名字
 * @return observerobj
 * @note 创建一个观察者对象
 */
Observer_t* Observer_new(char *name)
{
    Observer_t * p;
    
    p = malloc(sizeof(*p));
    if (!p)
        return NULL;
    
    memcpy(p->name, name, strlen(name));
    p->adapter = adapter;
    p->update_proc = update_proc;
    return p;
}

/**
 * @brief Subject_new
 * @param name 对象名字
 * @return subjectobj
 * @note 创建一个主题对象
 */
Subject_t* Subject_new(char * name)
{
    Subject_t * p;

    p = malloc(sizeof(*p));
    if (!p)
        return NULL;
    memset(p, 0x00, sizeof(*p));
    memcpy(p->name, name, strlen(name));
    p->add = add;
    p->del = del;
    p->notify = notify;
}

int main(void)
{
    Subject_t *subject;
    Observer_t *observerA;
    Observer_t *observerB;
    Observer_t *observerC;
    
    printf("start to create subjecter and observer.....\n");
    // 创建一个主题
    subject = Subject_new("creater");
    //创建多个消费者
    observerA = Observer_new("readerA");
    observerB = Observer_new("readerB");
    observerC = Observer_new("readerC");

    // 添加消费者到观察者列表
    subject->add(subject, observerA);
    subject->add(subject, observerB);
    subject->add(subject, observerC);
    
    // 通知给所有读者
    subject->notify(subject, "csdn-blog");
}

六.总结

当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象有待改变的时候,应该考虑使用观察者模式,同时观察者模式所做的工作也是在解除耦合,各个对象互为独立工作。

发布了45 篇原创文章 · 获赞 38 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/muchong123/article/details/104876933
今日推荐