设计模式在C中的应用方式

在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);  
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值