技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 编程语言 --> 如何有效避免大量重复的switch分支

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

浏览:2059次  出处信息

   最近学习设计模式相关知识,结合前面的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. 从Java视角理解CPU上下文切换(Context Switch)    (阅读:5436)
  2. 从 if else 到 switch case 再到抽象    (阅读:2487)
  3. JavaScript:假如default不是switch的最后一项    (阅读:2100)
  4. Switch Case中的经典    (阅读:1888)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1