观察者模式(C语言实现)

一. 概述

Observer 模式要解决的问题为:建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个“一”的多也能够同步改变。

Sbuject 相当于通知者,它提供依赖于它的观察者Observer 的注册(Attach)和注销(Detach)操作,并且提供了使得依赖于它的所有观察者同步的操作(Notify)。

Observer 相当于观察者,则提供一个Update操作,注意这里的 Observer 的 Update 操作并不在Observer 改变了Subject目标状态的时候就对自己进行更新,这个更新操作要延迟到 Subject 对象发出 Notify 通知所有 Observer 进行修改(调用Update)。

二. 举例

最常见的一个例子就是:对同一组数据进行统计分析时候,我们希望能够提供多种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变。

结构关系图如下:

DataSubject : 我们就认为是原始数据。

SheetObserver:就认为是表格,用来显示原始数据用的。

ChartObserver :就认为是图表,也是来显示原始数据的。

代码如下:

abstractClass.h

#ifndef ABSTRACTCLASS_H
#define ABSTRACTCLASS_H

#include <stdlib.h>
#include <stdarg.h>

typedef struct {
    size_t size;
    void* (*ctor)(void *_self, va_list *params);
    void* (*dtor)(void *_self);
} AbstractClass;

#endif

subject.h

#ifndef SUBJECT_H
#define SUBJECT_H

#include <stdlib.h>
#include <stdarg.h>

typedef struct {
    size_t size;
    void* (*ctor)(void *_self, va_list *params);
    void* (*dtor)(void *_self);
    void (*attach)(void *_self, void *_obv);  // Observer
    void (*detach)(void *_self, void *_obv);  // Observer
    void (*notify)(const void *_self);
    void (*setstate)(void *_self, char *_st);
    char *(*getstate)(const void *_self);
} Subject;

#endif

dataSubject.h

#ifndef DATASUBJECT_H
#define DATASUBJECT_H

typedef struct {
    const void *_;
    void *obvs;
    char *st;
} _DataSubject;

const void *DataSubject;

#endif

dataSubject.c

#include "subject.h"
#include "datasubject.h"
#include "new.h"
#include "singleList.h"
#include "observer.h"
#include <stdarg.h>
#include <stdlib.h>
#include <assert.h>

static void *dataSubjectCtor(void *_self, va_list *params) {
    _DataSubject *self = _self;

    self->obvs = New(SingleList);

    return self;
}

static void *dataSubjectDtor(void *_self) {
    _DataSubject *self = _self;

    Delete(self->obvs);
    self->obvs = NULL;

    return self;
}

static void dataSubjectAttach(void *_self, void *_obv) {
    _DataSubject *self = _self;
    Insert(self->obvs, _obv);
}

static void dataSubjectDetach(void *_self, void *_obv) {
    _DataSubject *self = _self;
    Remove(self->obvs, _obv);
}

static void update(void *_obv, va_list *params) {
    Observer **obv = _obv;

    void *sub = va_arg(*params, void*);
    assert(_obv && *obv && (*obv)->update);
    (*obv)->update(_obv, sub);
}

static void dataSubjectNotify(const void *_self) {
    const _DataSubject *self = _self;
    Iterator(self->obvs, update, _self);
}

static void dataSubjectSetState(void *_self, char *_st) {
    _DataSubject *self = _self;
    self->st = _st;
}

static char *dataSubjectGetState(const void *_self) {
    const _DataSubject *self = _self;
    return self->st;
}

static const Subject dataSubject = {
    sizeof(_DataSubject),
    dataSubjectCtor,
    dataSubjectDtor,
    dataSubjectAttach,
    dataSubjectDetach,
    dataSubjectNotify,
    dataSubjectSetState,
    dataSubjectGetState
};

const void *DataSubject = &dataSubject;

observer.h

#ifndef OBSERVER_H
#define OBSERVER_H

#include <stdlib.h>
#include <stdarg.h>

typedef struct {
    size_t size;
    void* (*ctor)(void* _self, va_list *params);
    void* (*dtor)(void *_self);
    void (*update)(void *_self, const void *sub);  // Subject
    void (*printinfo)(const void *_self);
} Observer;

#endif

sheetObserver.h

#ifndef SHEETOBSERVER_H
#define SHEETOBSERVER_H

typedef struct {
    const void *_;
    char *st;
    void *sub;
} _SheetObserver;

const void *SheetObserver;

#endif

sheetObserver.c

#include "observer.h"
#include "sheetobserver.h"
#include "subject.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

static void* sheetObserverCtor(void *_self, va_list *params) {
    _SheetObserver *self = _self;

    self->sub = va_arg(*params, void*);

    const Subject **sub = self->sub;

    assert(self->sub && *sub && (*sub)->attach);
    (*sub)->attach(self->sub, _self);

    return self;
}

static void *sheetObserverDtor(void *_self) {
    _SheetObserver *self = _self;
    const Subject **sub = self->sub;

    assert(self->sub && *sub && (*sub)->detach);
    (*sub)->detach(self->sub, _self);
    self->sub = NULL;

    return self;
}

static void sheetObserverPrintInfo(const void *_self) {
    const _SheetObserver *self = _self;

    fprintf(stdout, "SheetObserver: %s\n", self->st);
}

static void sheetObserverUpdate(void *_self, const void *_sub) {
    _SheetObserver *self = _self;
    const Subject * const *sub = _sub;

    assert(_sub && *sub && (*sub)->getstate);
    self->st = (*sub)->getstate(_sub);

    sheetObserverPrintInfo(_self);
}

static const Observer _sheetObserver = {
    sizeof(_SheetObserver),
    sheetObserverCtor,
    sheetObserverDtor,
    sheetObserverUpdate,
    sheetObserverPrintInfo
};

const void *SheetObserver = &_sheetObserver;

chatObserver.h

#ifndef CHATOBSERVER_H
#define CHATOBSERVER_H

typedef struct {
    const void *_;
    char *st;
    void *sub;
} _ChatObserver;

const void *ChatObserver;

#endif

chatObserver.c

#include "observer.h"
#include "chatobserver.h"
#include "subject.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

static void* chatObserverCtor(void *_self, va_list *params) {
    _ChatObserver *self = _self;

    self->sub = va_arg(*params, void*);

    const Subject **sub = self->sub;

    assert(self->sub && *sub && (*sub)->attach);
    (*sub)->attach(self->sub, _self);

    return self;
}

static void *chatObserverDtor(void *_self) {
    _ChatObserver *self = _self;
    const Subject **sub = self->sub;

    assert(self->sub && *sub && (*sub)->detach);
    (*sub)->detach(self->sub, _self);
    self->sub = NULL;

    return self;
}

static void chatObserverPrintInfo(const void *_self) {
    const _ChatObserver *self = _self;

    fprintf(stdout, "ChatObserver: %s\n", self->st);

}

static void chatObserverUpdate(void *_self, const void *_sub) {
    _ChatObserver *self = _self;
    const Subject * const *sub = _sub;

    assert(_sub && *sub && (*sub)->getstate);
    self->st = (*sub)->getstate(_sub);

    chatObserverPrintInfo(_self);
}

static const Observer _chatObserver = {
    sizeof(_ChatObserver),
    chatObserverCtor,
    chatObserverDtor,
    chatObserverUpdate,
    chatObserverPrintInfo
};

const void *ChatObserver = &_chatObserver;

list.h

#ifndef LIST_H
#define LIST_H

#include <stdarg.h>
#include <stdlib.h>

typedef void (*Print_FN)(void* data);
typedef void (*Handle_FN)(void *node, va_list *params);

typedef struct {
    size_t size;
    void* (*ctor)(void *_self, va_list *params);
    void* (*dtor)(void *_self);
    void (*insert)(const void *_self, void *data);
    void (*remove)(const void *_self, void *data);
    void (*iterator)(const void *_self, Handle_FN handle_fn, va_list *params);
    void (*print)(const void *_self, Print_FN print_fn);
} List;

#endif

singleList.h

#ifndef SINGLELIST_H
#define SINGLELIST_H

typedef struct _Node {
    void *data;
    struct _Node *next;
} Node;

typedef struct {
    const void *_;
    Node *head;
} _SingleList;

extern const void *SingleList;

#endif

singleList.c

#include "list.h"
#include "singleList.h"
#include "new.h"
#include <stdlib.h>

static void *singleListCtor(void *_self, va_list *params) {
    _SingleList *self = _self;

    self->head = (Node*)calloc(1, sizeof(Node));

    return self;
}

static void *singleListDtor(void *_self) {
    _SingleList *self = _self;
    Node **p = &self->head;

    while ((*p) != NULL) {
        Node *node = *p;
        *p = node->next;
        free(node);
    }

    return self;
}

static void singleListInsert(const void *_self, void *data) {
    const _SingleList *self = _self;
    Node *node = (Node*)calloc(1, sizeof(Node));

    Node **p = (Node **)&self->head;
    for (; (*p) != NULL; p = &(*p)->next) {
        ;
    }

    node->data = data;
    node->next = *p;
    *p = node;
}

static void singleListRemove(const void *_self, void *data) {
    const _SingleList *self = _self;
    Node **p = (Node **)&self->head;

    while ((*p) != NULL) {
        Node *node = *p;
        if (node->data == data) {
            *p = node->next;
        } else {
            p = &(*p)->next;
        }
    }
}

static void singleListIterator(const void *_self, Handle_FN handle_fn, va_list *params) {
    const _SingleList *self = _self;
    Node **p = &self->head->next;

    for (; (*p) != NULL; p = &(*p)->next) {
        va_list args;
        va_copy(args, *params);
        handle_fn((*p)->data, &args);
        va_end(args);
    }
}

static void singleListPrint(const void *_self, Print_FN print_fn) {
    const _SingleList *self = _self;
    Node **p = &self->head->next;

    while ((*p) != NULL) {
        print_fn((*p)->data);
        p = &(*p)->next;
    }
}

static const List _singleList = {
    sizeof(_SingleList),
    singleListCtor,
    singleListDtor,
    singleListInsert,
    singleListRemove,
    singleListIterator,
    singleListPrint,
};

const void *SingleList = &_singleList;

new.h

#ifndef NEW_H
#define NEW_H

#include "list.h"

void *New(const void *_class, ...);
void Delete(void *_class);
void SetState(void *_subject, char *_st);
void Notify(const void *_subject);
void Update(void *_observer, const void *_subject);
void Insert(void *_list, void *_item);
void Remove(void *_list, void *_item);
void Iterator(const void *list, Handle_FN handle_fn, ...);
void Print(void *_list, Print_FN print_fn);

#endif

new.c

#include "new.h"
#include "abstractClass.h"
#include "singleList.h"
#include "subject.h"
#include "observer.h"
#include <assert.h>

void *New(const void *_class, ...) {
    const AbstractClass *class = _class;

    void *p = calloc(1, class->size);

    assert(p);
    *(const AbstractClass **)p = class;

    if (class->ctor) {
        va_list params;

        va_start(params, _class);
        p = class->ctor(p, ¶ms);
        va_end(params);
    }

    return p;
}

void Delete(void *_class) {
    const AbstractClass **class = _class;

    if (_class && *class && (*class)->dtor) {
        _class = (*class)->dtor(_class);
    }

    free(_class);
}

void SetState(void *_subject, char *_st) {
    Subject **subject = _subject;

    if (_subject && *subject && (*subject)->setstate) {
        (*subject)->setstate(_subject, _st);
    }
}

void Notify(const void *_subject) {
    const Subject * const *subject = _subject;

    if (_subject && *subject && (*subject)->notify) {
        (*subject)->notify(_subject);
    }
}

void Update(void *_observer, const void *_subject) {
    Observer **observer = _observer;

    if (_observer && *observer && (*observer)->update) {
        (*observer)->update(_observer, _subject);
    }
}

void Insert(void *_list, void *_item) {
    ((const List*)SingleList)->insert(_list, _item);
}

void Remove(void *_list, void *_item) {
    ((const List*)SingleList)->remove(_list, _item);
}

void Iterator(const void *_list, Handle_FN handle_fn, ...) {
    va_list params;
    va_start(params, handle_fn);
    ((const List*)SingleList)->iterator(_list, handle_fn, ¶ms);
    va_end(params);
}

void Print(void *_list, Print_FN print_fn) {
    ((const List*)SingleList)->print(_list, print_fn);
}

main.c

#include "new.h"
#include "datasubject.h"
#include "sheetobserver.h"
#include "chatobserver.h"

int main(int argc, char *argv[]) {
    void *sub = New(DataSubject);

    void *o1 = New(SheetObserver, sub);
    void *o2 = New(ChatObserver, sub);

    SetState(sub, "old data");
    Notify(sub);

    SetState(sub, "new data");
    Notify(sub);

    Update(o1, sub);

    return 0;
}

图片来源:http://blog.csdn.net/hmsiwtv/article/details/9626967

时间: 2024-10-11 03:49:16

观察者模式(C语言实现)的相关文章

C语言的观察者模式

/*hdr ** Copyright ... ** AUTHOR MichaelMa ** DATE 4-May-2014 ** DESCRIPTION implement a mode of observer in C ** NOTE may be some bugs */ #include <stdio.h> #include <stdlib.h> #include <string.h> /***************************DEFINES****

用java语言实现一个观察者模式

观察者模式(也被称为发布/订阅模式)提供了避免组件之间紧密耦合的另一种方法,它将观察者和被观察的对象分离开.在该模式中,一个对象通过添加一个方法(该方法允许另一个对象,即观察者注册自己)使本身变得可观察.当可观察的对象更改时,它会将消息发送到已注册的观察者.这些观察者收到消息后所执行的操作与可观察的对象无关这种模式使得对象可以相互对话,而不必了解原因.Java语言与C#语言的事件处理机制就是采用的此种设计模式. 例如,用户界面(同一个数据可以有多种不同的显示方式)可以作为观察者,业务数据是被观察

新手码农浅谈观察者模式(java语言简单实现)

一:什么是观察者模式: 官方定义:定义对象间一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 举个例子,很多人都会订阅天气预报,当气象台获得明天的天气情况(目标对象)时,就会短信通知订阅了天气预报的人(观察者),然后订阅者就会根据明天天气情况做出相应的处理(呆在家?出去踏青?出去购物...) 二:观察者模式的两个角色: 第一个角色:目标对象(subject),被观察者关注的对象,它的改变引起观察者的改变,例如上面提到的天气情况. 第二个角色:观察者(o

《JAVA与模式》之观察者模式

观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式.模型-视图(Model/View)模式.源-监听器(Source/Listener)模式或从属者(Dependents)模式. 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 观察者模式的结构 一个软件系统里面包含了各种对象,就像一片欣欣向荣的森林充满了各种生物一样.在一片森林中,各种生物彼此依赖和约束

java:从消息机制谈到观察者模式

本文接编程思想之消息机制,读者可以结合编程思想之消息机制一起阅读,也可以直接从本文开始阅读. 从简单的例子开始 同样,我们还是先看一个简单例子:创建一个窗口实现加法的计算功能.其效果如下: 图1: 加法计算 Calculator.java: import javax.swing.*; import javax.swing.border.BevelBorder; import java.awt.*; import java.awt.event.ActionEvent; import java.aw

C#设计模式-观察者模式

前言 最近开始花点心思研究下设计模式,主要还是让自己写的代码可重用性高.保证代码可靠性.所谓设计模式,我找了下定义:是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.毫无疑问,设计模式于己于他人于系统都是多赢的:设计模式使代码编制真正工程化:设计模式是软件工程的基石脉络,如同大厦的结构一样. 为什么要提倡“Design Pattern(设计模式)”? 根本原因是为了代码复用,增加可维护性.因此这次我们来学习下设计模式,最后会通过C#语言来实现这些设计模式作为例子,深刻理解其中的

观察者模式(KVO和通知中心)

苹果其实在语言层面为我们做了很多事,比如Category实现装饰模式的意图,target-action实现命令模式意图等等,对于观察者模式,苹果也提供了KVO和通知中心,给开发者提供了极大的遍历. 观察着模式即一个对象发出广播,然后某些对象可以在得知这个广播之后做相应的反应. KVO用来监控某个变量,是一种局部性的监听机制,使用方式如下: 首先,为被检测的变量添加一个观察者: 1 [被监测对象 addObserver:self forKeyPath:@"xxx" options:NSK

java设计模式02观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 这里主要讲一下学习内置观察者的记录,在JAVA语言的java.util库里面,提供了一个Observable类以及一个Observer接口,构成JAVA语言对观察者模式的支持. Observer接口 这个接口只定义了一个方法,即update()方法,当被观察者对象的状态发生变化时,被观察者对象的notifyObservers()方法就会调用

[设计模式]&lt;9&gt;. C++与观察者模式(observer pattern)

作者:默默地EEer 原文:http://www.cnblogs.com/hebaichuanyeah/p/6091694.html 意图: 定义对象间一对多的依赖关系,使得一个对象被改变,其他对象被更新. java的事件机制就是一个观察者模式,当事件发生,所有的事件接收者执行事件响应函数. 实现观察者模式,首先需要定义一个"观察者类(observer)"接口,在该类里面定义一个纯虚的事件响应函数. 并且需要一个"目标类(subject)",该类里面包含一个Set/