/* Copyright(C) 2009 Yoshinori Oota All rights reserved. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* ObserverList Inteface */
struct ObserverList {
struct Observer* observer_;
struct ObserverList* next_;
};
struct ObserverList* New_ObserverList(struct Observer* observer);
void Delete_ObserverList(struct ObserverList* list);
void Delete_ObserverListAt(struct ObserverList* list);
/* Observer Interface */
struct Observer {
char* id_;
void (*update)(struct Observer* pthis ,const char* arg);
void (*message)(struct Observer* pthis ,const char* arg);
};
struct Observer* New_Observer(const char* id);
void Delete_Observer(struct Observer* observer);
void Observer_update(struct Observer* pthis ,const char* arg);
void Observer_message(struct Observer* pthis ,const char* arg);
/* Observable Interface */
void Observable_addObserver(struct Observer* observer);
void Observable_deleteObserver(struct Observer* observer);
void Observable_private_notifyObservers(const char* arg);
void Observable_write(const char* arg);
/* ObeserList Implementation */
struct ObserverList* New_ObserverList(struct Observer* observer) {
struct ObserverList* list = NULL;
list = (struct ObserverList*)malloc(sizeof(struct ObserverList));
list->observer_ = observer;
list->next_ = NULL;
return list;
}
void Delete_ObserverList(struct ObserverList* list) {
struct ObserverList* tmp = NULL;
if (list == NULL) {
return;
}
while (list != NULL) {
tmp = list->next_;
free(list);
list = tmp;
}
return;
}
void Delete_ObserverListAt(struct ObserverList* list) {
if (list == NULL) {
return;
}
free(list);
list = NULL;
return;
}
/* Observer Class Implementation */
struct Observer* New_Observer(const char* id) {
struct Observer* observer = NULL;
char* buf = NULL;
observer = (struct Observer*)malloc(sizeof(struct Observer));
buf = (char*)malloc(strlen(id)+1);
strcpy(buf, id);
observer->id_ = buf;
observer->update = &Observer_update;
observer->message = &Observer_message;
return observer;
}
void Delete_Observer(struct Observer* observer) {
if (observer == NULL) {
return;
}
free(observer->id_);
observer->id_ = NULL;
free(observer);
observer = NULL;
return;
}
void Observer_message(struct Observer* pthis ,const char* arg) {
char* msg = NULL;
char* l = "[";
char* r = "'s msg]";
int len = 0;
len = strlen(l)+strlen(pthis->id_)+strlen(r)+strlen(arg)+1;
msg = (char*)malloc(len);
strcpy(msg ,l);
strcat(msg ,pthis->id_);
strcat(msg ,r);
strcat(msg ,arg);
Observable_write(msg);
return;
}
void Observer_update(struct Observer* pthis, const char* arg) {
printf("%s> %s\n" ,pthis->id_, arg);
return;
}
/* Observable Implementation */
struct ObserverList* gObserversTop = NULL;
struct ObserverList* gObserversLast = NULL;
void Observable_addObserver(struct Observer* observer) {
struct ObserverList* list = NULL;
list = New_ObserverList(observer);
if (gObserversTop == NULL) {
gObserversTop = list;
gObserversLast = list;
} else {
gObserversLast->next_ = list;
gObserversLast = list;
}
return;
}
void Observable_deleteObserver(struct Observer* observer) {
struct ObserverList* cur = NULL;
struct ObserverList* prv = NULL;
if (gObserversTop == NULL) return;
cur = gObserversTop;
if (strcmp(cur->observer_->id_ ,observer->id_) == 0) {
gObserversTop = gObserversTop->next_; /* 先頭をはずす */
Delete_ObserverListAt(cur); /* 先頭のリストを開放 */
return;
}
while (cur != NULL) {
prv = cur;
cur = cur->next_;
if (strcmp(cur->observer_->id_ ,observer->id_) == 0) {
prv->next_ = cur->next_; /* 一つ前の要素と次の要素を連結 */
Delete_ObserverListAt(cur);
return;
}
}
return;
}
void Observable_Clean() {
Delete_ObserverList(gObserversTop);
gObserversLast = NULL;
return;
}
void Observable_private_notifyObservers(const char* arg) {
struct ObserverList* cur = NULL;
cur = gObserversTop;
while (cur != NULL) {
cur->observer_->update(cur->observer_ ,arg);
cur = cur->next_;
}
return;
}
void Observable_write(const char* arg) {
Observable_private_notifyObservers(arg);
return;
}
int main() {
struct Observer* a = New_Observer("yoshi");
struct Observer* b = New_Observer("chako");
Observable_addObserver(a);
Observable_addObserver(b);
a->message(a ,"Hello Everybody!");
b->message(b ,"Goodbye Everybody!");
Observable_deleteObserver(a);
Observable_deleteObserver(b);
Delete_Observer(a);
Delete_Observer(b);
Observable_Clean();
return 0;
}
|