大话设计模式C语言之责任链模式

责任链模式

责任链模式(Chain of Responsibility)是一种行为设计模式,允许你将请求沿着处理者链进行发送。收到请求后每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。

案例代码

抽象请求处理者

处理者(Handler)声明了所有具体处理者的通用接口。该接口通常仅包含单个方法用于请求处理,但有时其还会包含一个设置链上下个处理者的方法。

抽象处理者外部接口 handler.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef HANDLER_H
#define HANDLER_H

typedef struct Handler Handler;

/* 错误码定义 */
typedef enum {
HANDLER_OK = 0,
HANDLER_STOP = 1,
HANDLER_ERROR = -1
} HandlerStatus;

/* 对外接口 */
HandlerStatus handler_handle(Handler *handler, void *request);
void handler_set_next(Handler *handler, Handler *next);
void handler_destroy(Handler *handler);

#endif

抽象处理者内部接口 handler_internal.h
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef HANDLER_INTERNAL_H
#define HANDLER_INTERNAL_H

#include "handler.h"

struct Handler {
HandlerStatus (*handle)(Handler *self, void *request);
void (*destroy)(Handler *self);
Handler *next;
};

#endif

抽象处理者实现 handler.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "handler_internal.h"

HandlerStatus handler_handle(Handler *handler, void *request)
{
if (!handler || !handler->handle)
return HANDLER_ERROR;

HandlerStatus status = handler->handle(handler, request);

if (status == HANDLER_OK && handler->next)
return handler_handle(handler->next, request);

return status;
}

void handler_set_next(Handler *handler, Handler *next)
{
if (handler)
handler->next = next;
}

void handler_destroy(Handler *handler)
{
if (!handler) return;

if (handler->next)
handler_destroy(handler->next);

if (handler->destroy)
handler->destroy(handler);
}

请求对象

请求对象接口 log_message.h
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef LOG_MESSAGE_H
#define LOG_MESSAGE_H

typedef struct LogMessage LogMessage;

LogMessage *log_message_create(int level, int authorized, const char *text);
int log_message_level(LogMessage *msg);
int log_message_authorized(LogMessage *msg);
const char *log_message_text(LogMessage *msg);
void log_message_destroy(LogMessage *msg);

#endif

请求对象实现 log_message.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdlib.h>
#include <string.h>
#include "log_message.h"

struct LogMessage {
int level;
int authorized;
char *text;
};

LogMessage *log_message_create(int level, int authorized, const char *text)
{
LogMessage *msg = malloc(sizeof(LogMessage));
if (!msg) return NULL;

msg->level = level;
msg->authorized = authorized;
msg->text = strdup(text);

return msg;
}

int log_message_level(LogMessage *msg)
{
return msg ? msg->level : 0;
}

int log_message_authorized(LogMessage *msg)
{
return msg ? msg->authorized : 0;
}

const char *log_message_text(LogMessage *msg)
{
return msg ? msg->text : NULL;
}

void log_message_destroy(LogMessage *msg)
{
if (!msg) return;
free(msg->text);
free(msg);
}

具体处理者

具体处理者(Concrete Handlers)包含处理请求的实际代码。每个处理者接收到请求后,都必须决定是否进行处理,以及是否沿着链传递请求。

底层处理者
消息过滤 debug_filter.h
1
2
3
4
5
6
7
8
9
10
#ifndef DEBUG_FILTER_H
#define DEBUG_FILTER_H

#include "handler.h"

Handler *debug_filter_create(int min_level);

#endif


消息过滤 debug_filter.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdlib.h>
#include <stdio.h>
#include "handler_internal.h"
#include "debug_filter.h"
#include "log_message.h"

typedef struct {
Handler base;
int min_level;
} DebugFilter;

static HandlerStatus handle(Handler *self, void *request)
{
DebugFilter *filter = (DebugFilter *)self;
LogMessage *msg = (LogMessage *)request;

if (log_message_level(msg) < filter->min_level) {
printf("DebugFilter: message filtered\n");
return HANDLER_STOP;
}

return HANDLER_OK;
}

static void destroy(Handler *self)
{
free(self);
}

Handler *debug_filter_create(int min_level)
{
DebugFilter *filter = malloc(sizeof(DebugFilter));
if (!filter) return NULL;

filter->base.handle = handle;
filter->base.destroy = destroy;
filter->base.next = NULL;
filter->min_level = min_level;

return (Handler *)filter;
}

中层处理者
权限检查 auth_filter.h
1
2
3
4
5
6
7
8
9
#ifndef AUTH_FILTER_H
#define AUTH_FILTER_H

#include "handler.h"

Handler *auth_filter_create(void);

#endif

权限检查 auth_filter.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdlib.h>
#include <stdio.h>
#include "handler_internal.h"
#include "auth_filter.h"
#include "log_message.h"

typedef struct {
Handler base;
} AuthFilter;

static HandlerStatus handle(Handler *self, void *request)
{
(void)self;
LogMessage *msg = (LogMessage *)request;

if (!log_message_authorized(msg)) {
printf("AuthFilter: unauthorized\n");
return HANDLER_STOP;
}

return HANDLER_OK;
}

static void destroy(Handler *self)
{
free(self);
}

Handler *auth_filter_create(void)
{
AuthFilter *filter = malloc(sizeof(AuthFilter));
if (!filter) return NULL;

filter->base.handle = handle;
filter->base.destroy = destroy;
filter->base.next = NULL;

return (Handler *)filter;
}

高层处理者
控制台输出 console_logger.h
1
2
3
4
5
6
7
8
9
#ifndef CONSOLE_OUTPUT_H
#define CONSOLE_OUTPUT_H

#include "handler.h"

Handler *console_output_create(void);

#endif

控制台输出 console_logger.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdlib.h>
#include <stdio.h>
#include "handler_internal.h"
#include "console_output.h"
#include "log_message.h"

typedef struct {
Handler base;
} ConsoleOutput;

static HandlerStatus handle(Handler *self, void *request)
{
(void)self;
LogMessage *msg = (LogMessage *)request;

printf("ConsoleOutput: %s\n", log_message_text(msg));
return HANDLER_OK;
}

static void destroy(Handler *self)
{
free(self);
}

Handler *console_output_create(void)
{
ConsoleOutput *output = malloc(sizeof(ConsoleOutput));
if (!output) return NULL;

output->base.handle = handle;
output->base.destroy = destroy;
output->base.next = NULL;

return (Handler *)output;
}

测试客户端代码 main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "handler.h"
#include "debug_filter.h"
#include "auth_filter.h"
#include "console_output.h"
#include "log_message.h"

int main(void)
{
Handler *debug = debug_filter_create(2);
Handler *auth = auth_filter_create();
Handler *console = console_output_create();

handler_set_next(debug, auth);
handler_set_next(auth, console);

LogMessage *msg1 = log_message_create(1, 1, "low level log");
LogMessage *msg2 = log_message_create(3, 0, "no auth log");
LogMessage *msg3 = log_message_create(3, 1, "valid log");

handler_handle(debug, msg1);
handler_handle(debug, msg2);
handler_handle(debug, msg3);

log_message_destroy(msg1);
log_message_destroy(msg2);
log_message_destroy(msg3);

handler_destroy(debug);

while(1);
return 0;
}

总结

   当程序需要使用不同方式处理不同种类请求,而且请求类型和顺序预先未知时,可以使用责任链模式。该模式能将多个处理者连接成一条链。接收到请求后,它会“询问”每个处理者是否能够对其进行处理。这样所有处理者都有机会来处理请求。或必须按顺序执行多个处理者时也可以使用该模式,无论你以何种顺序将处理者连接成一条链,所有请求都会严格按照顺序通过链上的处理者。