在C语言中就不考虑封装了,考虑封装会导致代码易读性下降
1、与C++相同,抽象出公共接口,该步很关键
2、定义一个结构体,其成员为这些公共接口的函数指针。
3、具体的类如Page,Line等,第一个元素的类型必须是上述接口结构体(的指针),其它的做为结构体的私有数据放在后边。
4、该方法的缺点是“每个对象”都包含了上述结构体,当对象很多时会造成较多的内存浪费。
改进方法是在对象中定义接口结构体,改为定义接口结构体的指针,由于需要从ctx地址得到
整个结构体的地址,因此使用了多重指针。
以组合递归模式为例:
改进方法附后
struct Context
{
typedef int (*addChild)(struct Context *cur, struct Context *new);
typedef int (*draw)(struct Context *cur);
typedef int (*intersect)(struct Window *win);
typedef int (*getWindow)(struct Window *win);
}
struct Text
{
struct Context ctx;
struct Context **children;
int child_num;
struct Window window;
}
struct Line
{
struct Context ctx;
struct Context **children;
int child_num;
struct Window window;
}
struct Page
{
struct Context ctx;
struct Context **children;
int child_num;
struct Window window;
}
int main(void)
{
struct Page *page=malloc(sizeof(Page));
struct Text *text=malloc(sizeof(Text));
page->ctx.addChild = page_add_child;
page->ctx.draw = page_draw;
text->ctx.addChild = text_add_child;
text->ctx.draw = text_draw;
page->ctx.addChild(&page->ctx, &text->ctx);
}
由于每个对象都包含了接口结构体,如果接口数量和对象数量都很多,会造成大量内存浪费,
改进方法是使用指针,使内存占用降低至4字节。
struct Context
{
typedef int (*addChild)(struct Context **cur, struct Context **new);
typedef int (*draw)(struct Context **cur);
typedef int (*intersect)(struct Window *win);
typedef int (*getWindow)(struct Window *win);
}
struct Text
{
struct Context *ctx;
struct Context ***children;
int child_num;
struct Window window;
}
struct Line
{
struct Context *ctx;
struct Context ***children;
int child_num;
struct Window window;
}
struct Page
{
struct Context *ctx;
struct Context ***children;
int child_num;
struct Window window;
}
struct Context text_intf =
{
.addChild = text_addChild;
.draw = text_draw;
.intersect = text_intersect;
.getWindow = text_getWindow;
};
struct Context line_intf =
{
.addChild = line_addChild;
.draw = line_draw;
.intersect = line_intersect;
.getWindow = line_getWindow;
};
struct Context page_intf =
{
.addChild = page_addChild;
.draw = page_draw;
.intersect = page_intersect;
.getWindow = page_getWindow;
};
int main(void)
{
struct Page *page=malloc(sizeof(Page));
struct Text *text=malloc(sizeof(Text));
page->ctx = &page_intf;
text->ctx = &text_intf;
page->ctx->addChild(&page->ctx, &text->ctx);
}