IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

如何有效避免大量重复的switch分支

忘我的追寻 2013-10-29 12:21:06 累计浏览 2,802 次
本机暂存

   最近学习设计模式相关知识,结合前面的DRBD源码分析掌握了表驱动编程模式,这里作一些简单的总结。

   先看一段C代码:

typedef int type;    typedef void(*draw)(void);     struct shape    {        type t;        draw f;    };    struct rectange    {        type t;        int a;        draw f;    };    struct circle    {        type t;        int r;        draw f;    };    #define T1 0    #define T2 1    #define T3 2    void drawall(shape[] s, int count)    {        for (int i = 0; i != count; i++)        {            switch((s + i)->t)            {            case T1:                ((struct shape*)(s + i))->f();                break;            case T2:                ((struct rectange*)(s + i))->f();                break;            case T3:                ((struct circle*)(s + i))->f();                break;            default:                break;            }        }    }
代码中需要根据图形的形状去调用具体的draw方法,对type的判断只是为了确定该调用哪个结构体中的draw类型的函数。那么能否简化一下这个switch case呢?最简单的,修改各个抽象形状的结构体定义,然后定义一个共有的“基类”,即只定义类型和函数指针,将各种形状对象强转为“基类型”,然后统一调用函数指针即可,同时可以将指向形状对象的基类指针作为参数传入,在函数中再将基类型的指针转为具体的子类兴。达到去除case switch的目的。

   按照如上思路修改之后的代码应该是类似这样的:

struct base    {        type t;        draw f;    };    typedef int type;    typedef void(*draw)(struct base*);     struct shape    {        type t;        draw f;    };    struct rectange    {        type t;        draw f;        int a;    };    struct circle    {        type t;        draw f;        int r;    };    #define T1 0    #define T2 1    #define T3 2    void drawall(struct base[] s, int count)    {        struct base* b = s;        for (int i = 0; i != count; i++)        {            (b + i)->draw(b + i);        }    }
这样,要求所有的类型都应该“符合”base类型的结构,当出现不符合该类型的结构传入时,编译时并不会报错,运行时才会寻址错误。这样做不是特别好。

   按照表驱动模式进一步改造该代码:

struct config    {        type t;        int l;    };    typedef int type;    typedef void(*draw)(struct config*);     void drawshape(struct config*);    void drawsrectange(struct config*);    void drawcircle(struct config*);    #define T1 0    #define T2 1    #define T3 2    draw call_table[] = {        [T1] = {&drawshape},        [T2] = {&drawsrectange},        [T3] = {&drawcircle},    };    void drawall(struct config[] s, int count)    {        draw* d = call_table;        struct config* b = s;        for (int i = 0; i != count; i++)        {            (*(d + (b + i)->t))(b + i);        }    }

   这样代码看起来是简洁了,但是可读性降低了不少。

同分类推荐文章

  1. 如何写好设计文档? (2026-06-23 08:00:00)
  2. Designing With Uncertainty: How AI Supercharges Probabilistic Thinking (2026-06-16 23:00:00)
  3. The Benefits Of Cognitive Inclusion In UX Research (2026-06-10 18:00:00)

查看更多 设计 文章 →

建议继续学习

  1. 最常被程序员们谎称读过的计算机书籍 (累计阅读 9,158)
  2. JavaScript Interface 接口的实现 (累计阅读 6,992)
  3. 低级程序员和高级程序员的区别 (累计阅读 5,799)
  4. 用星际争霸讲解面向对象的概念 (累计阅读 5,223)
  5. 自己写的一个轻量级javascript框架的设计模式 (累计阅读 4,909)
  6. 多些时间能少写些代码 (累计阅读 4,857)
  7. 关于架构的一句话,还有一个实例 (累计阅读 4,704)
  8. 如此理解面向对象编程 (累计阅读 4,559)
  9. 每个程序员都应该了解的知识有哪些? (累计阅读 4,478)
  10. 你从未听说过的一种编程方式 (累计阅读 4,418)