11设计模式_职责链模式_C语言实现

职责链模式

1 模拟场景

假设我们要开发一个简单的防火墙软件。该防火墙软件允许用户自定义安全规则,并根据用户定义的安全规则阻止网络报文。

我们来思考下可能的实现方案:

方案一

在这里插入图片描述

由请求者分别向每条安全规则发起处理请求。

安全规则的细则(有多少条安全规则、哪条规则丢弃了报文、哪条规则没有丢弃报文)都暴露给请求者。

方案二

在这里插入图片描述

给所有安全规则的处理封装一个统一的处理者接口,请求者只需向该接口发起处理请求,不关心有多少条安全规则,也不关心具体那条安全规则丢弃了报文。

很显然,方案二将请求者和处理者解耦,方案二优于方案一。

此处方案二就是职责链模式的思想。

2 职责链模式简介

职责链模式用于解决请求者和处理者之间的耦合问题。处理者可能是多个对象中的某个时,职责链模式可以将请求者和处理者解耦。

请求者无需关心到底是哪个对象处理请求,只需要将请求发送到对应的“链”上。多个处理者根据某种顺序(比如:先后、优先级)排在“链”上,依次判断自己能否处理请求,如能则处理,如不能则把请求传给“链”上的下一个处理者。

3 使用职责链模式实现防火墙软件

参与者

  1. Handle: RuleHandle

定义安全规则处理接口,并实现安全规则的链式结构

  1. ConcreteHandle: Rule1Handle, Rule2Handle

实现一条具体的处理规则

  1. Client

准备待安全规则处理的报文,并安全规则链提交处理请求

UML

在这里插入图片描述

RuleHandle示例代码

rule_handle.h

#ifndef RULE_HANDLE_H
#define RULE_HANDLE_H

#define MAX_HANDLE_NUM 10

struct RuleHandle {
    struct RuleHandle *successor;
    void (*SetSuccessor)(struct RuleHandle *this, struct RuleHandle *newHandle);
    // return 0:被本规则拦截,丢弃报文, return 1:未被本规则拦截,继续
    int (*HandleRequest)(struct RuleHandle *this, int pktType); 
};

// 构造函数
void RuleHandle(struct RuleHandle *this);
// 析构函数
void _RuleHandle(struct RuleHandle *this);

#endif

rule_handle.c

#include "rule_handle.h"
#include <stddef.h>

static void SetSuccessor(struct RuleHandle *this, struct RuleHandle *newHandle)
{
    this->successor = newHandle;
}

// 构造函数
void RuleHandle(struct RuleHandle *this)
{    
    this->successor = NULL;
    this->HandleRequest = NULL;
    this->SetSuccessor = SetSuccessor;
}

// 析构函数
void _RuleHandle(struct RuleHandle *this)
{
    this->successor = NULL;
    this->HandleRequest = NULL;
    this->SetSuccessor = NULL;
}

Rule1Handle示例代码

rule1_handle.h

#include "rule_handle.h"

// 构造函数
void Rule1Handle(struct RuleHandle *this);

// 析构函数
void _Rule1Handle(struct RuleHandle *this);

rule1_handle.c

#include "rule1_handle.h"
#include <stddef.h>

static int HandleRequest(struct RuleHandle *this, int pktType)
{
    if (pktType == 3) {
        return 0;
    }
    
    if (this->successor != NULL) {
        return this->successor->HandleRequest(this->successor, pktType);
    }

    return 1;
}

// 构造函数
void Rule1Handle(struct RuleHandle *this)
{    
    RuleHandle(this);
    this->HandleRequest = HandleRequest;
}

// 析构函数
void _Rule1Handle(struct RuleHandle *this)
{
    RuleHandle(this);
}

Rule2Handle示例代码

rule2_handle.h

#include "rule_handle.h"

// 构造函数
void Rule2Handle(struct RuleHandle *this);

// 析构函数
void _Rule2Handle(struct RuleHandle *this);

rule2_handle.c

#include "rule_handle.h"
#include <stddef.h>

static int HandleRequest(struct RuleHandle *this, int pktType)
{
    if (pktType == 5) {
        return 0;
    }
    
    if (this->successor != NULL) {
        return this->successor->HandleRequest(this->successor, pktType);
    }

    return 1;
}

// 构造函数
void Rule2Handle(struct RuleHandle *this)
{    
    RuleHandle(this);
    this->HandleRequest = HandleRequest;
}

// 析构函数
void _Rule2Handle(struct RuleHandle *this)
{
    RuleHandle(this);
}

客户端代码示例

#include "rule_handle.h"
#include "rule1_handle.h"
#include "rule2_handle.h"
#include <stdio.h> 

void main()
{
    //待防火墙处理的网络报文类型
    int pktStream[] = {1, 2, 3, 4, 5, 5, 1, 2, 3};

    struct RuleHandle rule1; // 丢弃类型为3的网络报文
    Rule1Handle(&rule1);

    struct RuleHandle rule2; // 丢弃类型为5的网络报文
    Rule2Handle(&rule2);
    rule1.SetSuccessor(&rule1, &rule2);

    int i;
    for (i = 0; i < (sizeof(pktStream) / sizeof(int)); i++) {
        printf("网络报文类型 %d : ", pktStream[i]);
        if (rule1.HandleRequest(&rule1, pktStream[i]) == 0) {
            printf("丢弃\n");
        } else {
            printf("不丢弃\n");
        }
    }
}

客户端显示示例

-bash-4.2# ./test
网络报文类型 1 : 不丢弃
网络报文类型 2 : 不丢弃
网络报文类型 3 : 丢弃
网络报文类型 4 : 不丢弃
网络报文类型 5 : 丢弃
网络报文类型 5 : 丢弃
网络报文类型 1 : 不丢弃
网络报文类型 2 : 不丢弃
网络报文类型 3 : 丢弃

猜你喜欢

转载自blog.csdn.net/weixin_46826913/article/details/107443335