職責鏈模式(C語言實現)

一. 概述

職責鏈模式:

使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它爲止。

二. 舉個例子

員工要求加薪

公司的管理者一共有三級:總經理、總監、經理,如果一個員工要求加薪,應該向主管的經理申請,如果加薪的數量在經理的職權內,那麼經理可以直接批准,否則將申請上交給總監。總監的處理方式也一樣,總經理可以處理所有請求。這就是典型的職責鏈模式,請求的處理形成了一條鏈,直到有一個對象處理請求。

結構圖如下:

假設:

經理可以處理薪水的範圍在:0~500
總監可以處理薪水的範圍在:500~1000
總經理可以處理薪水的範圍在:1000~2000

則代碼如下:


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

handle.h

#ifndef HANDLE_H
#define HANDLE_H

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

typedef struct {
    size_t size;
    void* (*ctor)(void *_self, va_list *params);
    void* (*dtor)(void *_self);
    void (*setSuccessor)(void *_self, void *succ);
    void *(*getSuccessor)(const void *_self);
    void (*handleRequest)(const void *_self, int request);
} Handle;


#endif

concreteHandleA.h

#ifndef CONCRETEHANDLEA_H
#define CONCRETEHANDLEA_H

typedef struct {
    const void *_;
    void *succ;
} _ConcreteHandleA;

extern const void *ConcreteHandleA;

#endif

concreteHandleA.c

#include "handle.h"
#include "concreteHandleA.h"
#include <stdlib.h>
#include <stdio.h>

static void *concreteHandleACtor(void *_self, va_list *params) {
    _ConcreteHandleA *self = _self;

    return self;
}

static void *concreteHandleADtor(void *_self) {
    _ConcreteHandleA *self = _self;

    self->succ = NULL;

    return self;
}

static void concreteHandleASetSuccessor(void *_self, void *_succ) {
    _ConcreteHandleA *self = _self;

    self->succ = _succ;
}

static void *concreteHandleAGetSuccessor(const void *_self) {
    const _ConcreteHandleA *self = _self;

    return self->succ;
}

static void concreteHandleAhandleRequest(const void *_self, int request) {
    if (request >= 0 && request < 500) {
        fprintf(stdout, "ConcreteHandleA deal with: %d\n", request);
    } else if (concreteHandleAGetSuccessor(_self) != NULL) {
        const Handle * const *succ = concreteHandleAGetSuccessor(_self);
        (*succ)->handleRequest(succ, request);
    } else {
        fprintf(stderr, "Can't deal with: %d\n", request);
    }
}

static const Handle _concreteHandleA = {
    sizeof(_ConcreteHandleA),
    concreteHandleACtor,
    concreteHandleADtor,
    concreteHandleASetSuccessor,
    concreteHandleAGetSuccessor,
    concreteHandleAhandleRequest
};

const void *ConcreteHandleA = &_concreteHandleA;
concreteHandleB.h

#ifndef CONCRETEHANDLEB_H
#define CONCRETEHANDLEB_H

typedef struct {
    const void *_;
    void *succ;
} _ConcreteHandleB;

extern const void *ConcreteHandleB;

#endif

concreteHandleB.c

#include "handle.h"
#include "concreteHandleB.h"
#include <stdlib.h>
#include <stdio.h>

static void *concreteHandleBCtor(void *_self, va_list *params) {
    _ConcreteHandleB *self = _self;

    return self;
}

static void *concreteHandleBDtor(void *_self) {
    _ConcreteHandleB *self = _self;

    self->succ = NULL;

    return self;
}

static void concreteHandleBSetSuccessor(void *_self, void *_succ) {
    _ConcreteHandleB *self = _self;

    self->succ = _succ;
}

static void *concreteHandleBGetSuccessor(const void *_self) {
    const _ConcreteHandleB *self = _self;

    return self->succ;
}

static void concreteHandleBhandleRequest(const void *_self, int request) {
    if (request >= 500 && request < 1000) {
        fprintf(stdout, "ConcreteHandleB deal with: %d\n", request);
    } else if (concreteHandleBGetSuccessor(_self) != NULL) {
        const Handle * const *succ = concreteHandleBGetSuccessor(_self);
        (*succ)->handleRequest(succ, request);
    } else {
        fprintf(stderr, "Can't deal with: %d\n", request);
    }
}

static const Handle _concreteHandleB = {
    sizeof(_ConcreteHandleB),
    concreteHandleBCtor,
    concreteHandleBDtor,
    concreteHandleBSetSuccessor,
    concreteHandleBGetSuccessor,
    concreteHandleBhandleRequest
};

const void *ConcreteHandleB = &_concreteHandleB;

concreteHandleC.h

#ifndef CONCRETEHANDLEC_H
#define CONCRETEHANDLEC_H

typedef struct {
    const void *_;
    void *succ;
} _ConcreteHandleC;

extern const void *ConcreteHandleC;

#endif

concreteHandleC.c

#include "handle.h"
#include "concreteHandleC.h"
#include <stdlib.h>
#include <stdio.h>

static void *concreteHandleCCtor(void *_self, va_list *params) {
    _ConcreteHandleC *self = _self;

    return self;
}

static void *concreteHandleCDtor(void *_self) {
    _ConcreteHandleC *self = _self;

    self->succ = NULL;

    return self;
}

static void concreteHandleCSetSuccessor(void *_self, void *_succ) {
    _ConcreteHandleC *self = _self;

    self->succ = _succ;
}

static void *concreteHandleCGetSuccessor(const void *_self) {
    const _ConcreteHandleC *self = _self;

    return self->succ;
}

static void concreteHandleChandleRequest(const void *_self, int request) {
    if (request >= 1000 && request < 2000) {
        fprintf(stdout, "ConcreteHandleC deal with: %d\n", request);
    } else if (concreteHandleCGetSuccessor(_self) != NULL) {
        const Handle * const *succ = concreteHandleCGetSuccessor(_self);
        (*succ)->handleRequest(succ, request);
    } else {
        fprintf(stderr, "Can't deal with: %d\n", request);
    }
}

static const Handle _concreteHandleC = {
    sizeof(_ConcreteHandleC),
    concreteHandleCCtor,
    concreteHandleCDtor,
    concreteHandleCSetSuccessor,
    concreteHandleCGetSuccessor,
    concreteHandleChandleRequest
};

const void *ConcreteHandleC = &_concreteHandleC;

new.h

#ifndef NEW_H
#define NEW_H

void *New(const void *_class, ...);
void Delete(void *_class);
void SetSuccessor(void *_handle, void *_succ);
void HandleRequest(void *_handle, int request);

#endif

new.c

#include "new.h"
#include "abstractClass.h"
#include "handle.h"
#include <stdarg.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.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 SetSuccessor(void *_handle, void *_succ) {
    Handle **handle = _handle;

    if (_handle && *handle && (*handle)->setSuccessor) {
        (*handle)->setSuccessor(_handle, _succ);
    }
}

void HandleRequest(void *_handle, int request) {
    Handle **handle = _handle;

    if (_handle && *handle && (*handle)->handleRequest) {
        (*handle)->handleRequest(_handle, request);
    }
}

main.c

#include "new.h"
#include "concreteHandleA.h"
#include "concreteHandleB.h"
#include "concreteHandleC.h"

int main(int argc, char *argv[]) {
    void *h1 = New(ConcreteHandleA);
    void *h2 = New(ConcreteHandleB);
    void *h3 = New(ConcreteHandleC);

    SetSuccessor(h1, h2);
    SetSuccessor(h2, h3);

    HandleRequest(h1, 300);
    HandleRequest(h1, 600);
    HandleRequest(h1, 1500);
    HandleRequest(h1, 3000);
    
    Delete(h1);
    Delete(h2);
    Delete(h3);
    
    return 0;
}


圖片來源:http://blog.csdn.net/hmsiwtv/article/details/9627307

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章