20.设计模式-职责链模式

职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

需求

流程申请审批,如加薪、请假

代码

业务类

c 复制代码
#include <stdio.h>
#include <string.h>
#include "uthash-master-src/src/uthash.h"

typedef enum {
    MANAGEER,
    DIRECTOR,
    GENERALMANGER,
    LEVELMAX
} Level;

typedef enum {
    ADDMONEY,
    REST,
    REQUESTMAX
} RequstType;

char *RequestContent[] = {
    "加薪",
    "请假"
};

typedef struct Request {
    RequstType type;
    int num;
} Request;

typedef struct Manager {
    Level level;
    char *name;
    // 假设只有一个直接上级
    struct Manager *superiors;
    void (*request)(struct Manager *, Request *);
} Manager;
// 经理
typedef struct CommonManger {
    Manager base;
} CommonManger;

void CommonMangerRequest(Manager *obj, Request *req) {
    if(req->type == REST && req->num <= 2) {
        printf("%s:%s 数量%d 被批准\n", obj->name, RequestContent[req->type], req->num);
    }
    else {
        obj->superiors->request(obj->superiors, req);
    }
}

Manager *InitCommonManager(char *name) {
    CommonManger *obj = (CommonManger *)malloc(sizeof(CommonManger));
    obj->base.level = MANAGEER;
    obj->base.name = name;
    // obj->base.superiors = superior;
    obj->base.request = CommonMangerRequest;
    return (Manager *)obj;
}
// 总监
typedef struct Director {
    Manager base;
} Director;

void DirectorRequest(Manager *obj, Request *req) {
    if(req->type == REST && req->num <= 5) {
        printf("%s:%s 数量%d 被批准\n", obj->name, RequestContent[req->type], req->num);
    }
    else {
        obj->superiors->request(obj->superiors, req);
    }
}

Manager *InitDirector(char *name) {
    Director *obj = (Director *)malloc(sizeof(Director));
    obj->base.level = DIRECTOR;
    obj->base.name = name;
    // obj->base.superiors = superior;
    obj->base.request = DirectorRequest;
    return (Manager *)obj;
}
// 总经理
typedef struct GeneralManager {
    Manager base;
} GeneralManager;

void GeneralManagerRequest(Manager *obj, Request *req) {
    if(req->type == REST) {
        printf("%s:%s 数量%d 被批准\n", obj->name, RequestContent[req->type], req->num);
    }
    else {
        if(req->num <= 500) {
            printf("%s:%s 数量%d 被批准\n", obj->name, RequestContent[req->type], req->num);
        }
        else {
            printf("%s:%s 数量%d 再说吧\n", obj->name, RequestContent[req->type], req->num);
        }
    }
}

Manager *InitGeneralManager(char *name) {
    GeneralManager *obj = (GeneralManager *)malloc(sizeof(GeneralManager));
    obj->base.level = GENERALMANGER;
    obj->base.name = name;
    // obj->base.superiors = superior;
    obj->base.request = GeneralManagerRequest;
    return (Manager *)obj;
}

typedef struct {
    char *name;
    Level level;
} WorkInfo;

typedef struct ChainOfResponsbility {
    WorkInfo pre;
    WorkInfo next;
} ChainOfResponsbility;

ChainOfResponsbility cofry[] = {
    {{"jingli",MANAGEER}, {"zongjian",DIRECTOR}},
    {{"zongjian",DIRECTOR}, {"zongjingli", GENERALMANGER}}
};

typedef Manager *(*CreateManagerInterface)(char *);

CreateManagerInterface cmi[] = {
    InitCommonManager,
    InitDirector,
    InitGeneralManager
};

typedef struct HashMap {
    char *name;
    Manager *manager;
    UT_hash_handle hh;
} HashMap;

客户端

c 复制代码
int main() {
    int n = sizeof(cofry)/sizeof(ChainOfResponsbility);
    HashMap *hashtable = NULL;
    HashMap *found;
    for(int i=0; i<n; i++) {
        Manager *pre, *next;
        HASH_FIND_STR(hashtable, cofry[i].pre.name, found);
        if(found == NULL) {
            found = (HashMap *)malloc(sizeof(HashMap));
            found->name = cofry[i].pre.name;
            HASH_ADD_STR(hashtable, name, found);
            found->manager = cmi[cofry[i].pre.level](cofry[i].pre.name);
        }
        pre = found->manager;
        HASH_FIND_STR(hashtable, cofry[i].next.name, found);
        if(found == NULL) {
            found = (HashMap *)malloc(sizeof(HashMap));
            found->name = cofry[i].next.name;
            HASH_ADD_STR(hashtable, name, found);
            pre->superiors = cmi[cofry[i].next.level](cofry[i].next.name);
            found->manager = pre->superiors;
        }
        else {
            pre->superiors = found->manager;
        }
    }
    printf("initial complete\n");
    HASH_FIND_STR(hashtable, cofry[0].pre.name, found);
    Manager *entry = found->manager;
    Request req[] = {
        {REST, 1},
        {REST, 3},
        {ADDMONEY, 500},
        {ADDMONEY, 1000}
    };
    n = sizeof(req)/sizeof(Request);
    for(int i=0; i<n; i++) {
        entry->request(entry, &(req[i]));
    }
    return 0;
}

客户端打印:

text 复制代码
jingli:请假 数量1 被批准
zongjian:请假 数量3 被批准
zongjingli:加薪 数量500 被批准
zongjingli:加薪 数量1000 再说吧

UML图

总结

  • 职责链模式的优点?
    职责模式的处理过程是当客户提交一个请求时,请求是沿链传递直至有一个ConcreteHandler对象负责处理它。这就使得接收者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用。
相关推荐
杨充18 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充19 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充19 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充19 小时前
2.面向对象的特性
设计模式
杨充19 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充19 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充19 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式