模板模式 (C语言实现)

一. 问题

在面向对象系统的分析与设计过程中经常会遇到这样一种情况:对于某一个业务逻辑(算法实现)在不同的对象中有不同的细节实现,但是逻辑(算法)的框架(或通用的应用算法)是相同的。Template提供了这种情况的一个实现框架。

二. 模式

Template 模式是采用继承的方式实现这一点:将逻辑(算法)框架放在抽象基类中,并定义好细节的接口,子类中实现细节

三. 代码

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);
    void (*templateMethod)(const void *_self);
    char *description;
} AbstractClass;

#endif

concreteClass1.h

#ifndef CONCRETECLASS1_H
#define CONCRETECLASS1_H

#include "abstractClass.h"

typedef struct {
    const void *abstractClass;
    void (*primitiveOperation1)(const void *_self);
    void (*primitiveOperation2)(const void *_self);
    int a;
} _ConcreteClass1;

extern const void *ConcreteClass1;

#endif


concreteClass1.c

#include "concreteClass1.h"
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>

static void *concreteClass1Ctor(void *_self, va_list *params) {
    _ConcreteClass1 *self = _self;
    const char *description = va_arg(*params, const char *);

    (*(AbstractClass **)self)->description = calloc(1, strlen(description) + 1);
    assert((*(AbstractClass **)self)->description);
    strncpy((*(AbstractClass **)self)->description, description, strlen(description) + 1);
    
    self->a = va_arg(*params, int);

    return self;
}

static void *concreteClass1Dtor(void *_self) {
    _ConcreteClass1 *self = _self;

    if (NULL != (*(AbstractClass **)self)->description) {
        free((*(AbstractClass **)self)->description);
        (*(AbstractClass **)self)->description = NULL;
    }
    self->a = 0;

    return self;
}

static void concreteClass1PrimitiveOperation1(const void *_self) {
    if (NULL != (*(const AbstractClass * const *)_self)->description) {
        fprintf(stdout, "%s\n", (*(const AbstractClass * const *)_self)->description);
    }
}

static void concreteClass1PrimitiveOperation2(const void *_self) {
    const _ConcreteClass1 *self = _self;

    fprintf(stdout, "%d\n", self->a);
}

static void concreteClass1TemplateMethod(const void* _self) {
    concreteClass1PrimitiveOperation1(_self);
    concreteClass1PrimitiveOperation2(_self);
}

static AbstractClass _concreteClass1 = {
    sizeof(_ConcreteClass1),
    concreteClass1Ctor,
    concreteClass1Dtor,
    concreteClass1TemplateMethod,
    NULL
};

const void *ConcreteClass1 = &_concreteClass1;

concreteClass2.h

#ifndef CONCRETECLASS2_H
#define CONCRETECLASS2_H

#include "abstractClass.h"

typedef struct {
    const void *abstractClass;
    void (*primitiveOperation1)(const void *_self);
    void (*primitiveOperation2)(const void *_self);
    double b;
} _ConcreteClass2;

extern const void *ConcreteClass2;

#endif

concreteClass2.c

#include "concreteClass2.h"
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>

static void *concreteClass2Ctor(void *_self, va_list *params) {
    _ConcreteClass2 *self = _self;
    const char *description = va_arg(*params, const char *);

    (*(AbstractClass **)self)->description = calloc(1, strlen(description) + 1);
    assert((*(AbstractClass **)self)->description);
    strncpy((*(AbstractClass **)self)->description, description, strlen(description) + 1);
    self->b = va_arg(*params, double);

    return self;
}

static void *concreteClass2Dtor(void *_self) {
    _ConcreteClass2 *self = _self;

    if (NULL != (*(AbstractClass **)self)->description) {
        free((*(AbstractClass **)self)->description);
        (*(AbstractClass **)self)->description = NULL;
    }
    self->b = 0;

    return self;
}

static void concreteClass2PrimitiveOperation1(const void *_self) {
    if (NULL != (*(const AbstractClass * const *)_self)->description) {
        fprintf(stdout, "%s\n", (*(const AbstractClass **)_self)->description);
    }    
}

static void concreteClass2PrimitiveOperation2(const void *_self) {
    const _ConcreteClass2 *self = _self;

    fprintf(stdout, "%f\n", self->b);
}

static void concreteClass2TemplateMethod(const void* _self) {
    concreteClass2PrimitiveOperation1(_self);
    concreteClass2PrimitiveOperation2(_self);
}

static AbstractClass _concreteClass2 = {
    sizeof(_ConcreteClass2),
    concreteClass2Ctor,
    concreteClass2Dtor,
    concreteClass2TemplateMethod,
    NULL
};

const void *ConcreteClass2 = &_concreteClass2;

new.h

#ifndef __NEW_H__
#define __NEW_H__

void *New(const void *_class, ...);
void Delete(void *_class);
void TemplateMethod(const void *_class);

#endif

new.c

#include "new.h"
#include "abstractClass.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 TemplateMethod(const void *_class) {
    const AbstractClass * const *class = _class;

    if (_class && *class && (*class)->templateMethod) {
        (*class)->templateMethod(_class);
    }
}

main.c

#include "new.h"
#include "concreteClass1.h"
#include "concreteClass2.h"

int main(int argc, char *argv[]) {
    void *p1 = New(ConcreteClass1, "ConcreteClass1", 10);
    void *p2 = New(ConcreteClass2, "ConcreteClass2", 20.1);

    TemplateMethod(p1);
    TemplateMethod(p2); 

    Delete(p1);
    Delete(p2);
    
    return 0;
}


图片来源:http://blog.csdn.net/hmsiwtv/article/details/9627019

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值