一. 问题
在面向对象系统的分析与设计过程中经常会遇到这样一种情况:对于某一个业务逻辑(算法实现)在不同的对象中有不同的细节实现,但是逻辑(算法)的框架(或通用的应用算法)是相同的。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
#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