表驱动法(Table-Driven )在程序中应用

Table-drive表驱动法--由税率问题引出

皮贝贝 posted @ 2008年7月05日 21:38 in 模式之灾 with tags 表驱动法 c++ , 2465 阅读

 问题引出:写一个医疗保险费率的程序,这些费率是随着年龄、性别、婚姻状况的不同情况而变化。

一般思路:我们可能会想到条件分支,好我们先看看条件分支的情况:

 

  1. if ( gendar == Male )
  2. {
  3.         if ( maritalStatus == Single )
  4.         {
  5.                 if ( age < 18 )
  6.                 {
  7.                         rate = 80.00;
  8.                 }
  9.                 else if ( age < 30 )
  10.                 {
  11.                         rate = 90.00;
  12.                 }
  13.                 //.......其他略
  14.         }
  15.         else if ( maritalStatus == Maried )
  16.         {
  17.                 //又是一串年龄判断分支
  18.         }
  19. }
  20. else if ( gendar == Female )
  21. {
  22.         //又是一串婚姻状况判断分支
  23. }
  24.  
  25.  

      可以看到上述的条件分支程序,写起来有多,读起来也是有些费时间,而且万一改动一点,比如增加一个婚姻状况(当然这是不可能的了,不过我们还是有时会面临这种类似的扩充),还要在增加好多代码。一个稍微明智的人可能会改为switch语句,这样看其来更易读些,还是难逃条件分支语句的缺陷。

     Table-drive 表驱动法是一种替代逻辑语句(if / else)的编程模式,其替代优点是简单清晰,尤其是在判断分支较多的情况时, 另一个显在的优势是可以放在文件中读取,这样一来,就可以就可以不改变源代码前提下更改一些表内容,正合元编程思想。

   
大而论之,三则:

1. 直接访问表
2. 索引访问表
3. 阶梯访问表
 

    下面我们就税率问题看看用表驱动法是如何解决的。

  先看看直接访问表法:把所有的税率放在数组的表中,其他的访问条件如年龄,婚姻状况,性别可以用数组下标来表示,我们先构建几个数据结构:

 

  1.  
  2. enum Gendar
  3. {
  4.         GendarFirst     =     0,
  5.         GendarMale      =     0,
  6.         GendarFemal     =     1,
  7.         GendarLast      =     1
  8. };
  9.  
  10. enum MaritalStatus
  11. {
  12.         MaritalStatusFirst      =     0,
  13.         MaritalStatusSingle     =     0,
  14.         MaritalStatusMarried    =     1,
  15.         MaritalStatusLast       =     1
  16. };
  17.  

因此我们的税率表就自然构造好了:

 

  1. double rateTable[GendarLast][MaritalStatusLast][MAX_AGE];

MAX_AGE是一个年龄最大值,每个年龄都有一个对应的税率。

我们可以正式用它了,看看怎么调用它吧:

 

  1. double rate = rateTable[gemdar][maritalStatus][age];

调用比起用条件分支判断语句简单吧。

 

上面我们讲到,每个年龄都有一个对应的税率,但是税率是按年龄段来分的,所以上述的直接访问表法有很多冗余信息,造成了空间浪费。

解决方法是我们可以加一个中间层,我们加了一个年龄转化函数,用来把实际年龄转化为一个年龄段,这样调用接口就变成了这样:

 

  1.  
  2. double getRate( Gendar gemdar, MaritalStatus maritalStatus, int age )
  3. {
  4.         int ageIndex = getAgeIndex( age );
  5.         return rateTable[gemdar][maritalStatus][ageIndex];
  6. }
  7.  

当然,在税率的表中,第三个数组下标就从年龄变成了年龄段:

 

  1. double rateTable[GendarLast][MaritalStatusLast][MAX_AGE_INDEX];

剩下的是我们如何实现中间层,我们就再增加一个数组表,:

 

  1.  
  2. int ageIndex[MAX_AGE_INDEX] = {020, 50, 60, 70, 80};
  3.  
  4. int getAgeIndex( int age )
  5. {
  6.         int iPos;
  7.         while ( ageIndex[iPos] < age ) iPos++;
  8.         return iPos-1;
  9. }

 

表驱动法是编程初学者的强大武器,可以在表中放元素,亦可以放函数指针,只要是有分支判断的地方几乎都可以一试拳脚。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter