表驱动方法编程
表驱动方法编程(Table-Driven Methods)是一种编程模式,适用场景:消除代码中频繁的if else或switch case的逻辑结构代码,使代码更加直白.
用例分析
假设让你实现一个返回每个月天数的函数(为简单起见不考虑闰年)。
仔细发现每月天数无外乎 28、30、31 三种,或许会用 switch-case 利用case穿透:
public static int getDayByMonth(int month){
if(month<1|| month>12){
throw new RuntimeException("month invalid parameter:"+month);
}
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return 31;
case 2:
return 28;
case 4:
case 6:
case 9:
case 11:
return 30;
default:
return -1;
}
}
这两种方法充斥了大量的逻辑判断,还凭空冒出了一大堆1,2,...,11,12这样的 Magic Number
表驱动处理起来就赏心悦目得多了:
static int monthDays[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
public static int getDayByMonth(int month){
if(month<1|| month>12){
throw new RuntimeException("month invalid parameter:"+month);
}
return monthDays[(month- 1)];
}
表驱动法编程的使用与访问方式:
①直接访问通过索引/key值来直接访问数组/集合
如:array[index]参考上面的月份获取天数的案例
或者map.get("传入的key值")集合获取
②间接通过索引/key值来直接访问数组/集合
100 种商品,每种商品都有一个 ID 号,但很多商品的描述都差不多,所以只有 30 条不同的描述,如何建立建立商品与商品描述的表?
方法是建立一个 100 长的索引和 30 长的描述,然后这些索引指向相应的描述(不同的索引可以指向相同的描述),这样就解决了表数据冗余的问题啦。
struct product_t {
char * id;
int desc_index;
};
const char * desc[] = {
"description_1",
"description_2",
...
"description_29",
"description_30"
};
const product_t goods [] = {
{"id_1", 3},
{"id_2", 1},
...
{"id_99", 12},
{"id_100", 5}
};
const char* desc_product (const char* id) {
for (const product_t & p : goods) {
if (strcmp(p.id, id) == 0) {
return desc[p.desc_index - 1];
}
}
return NULL;
}
③阶梯访问
例子:将百分制成绩转成五级分制(我们用的优、良、中、合格、不合格,西方用的 A、B、C、D和F),假定转换关系:
| Score | Degree |
|---|---|
| [90-100] | A |
| [80,90) | B |
| [70,80) | C |
| [60,70) | D |
| [0,60) | F |
const char gradeTable[] = {
'A', 'B', 'C', 'D', 'F'
};
const int downLimit[] = {
90, 80, 70, 60
};
int degree(int score)
{
int gradeLevel = 0;
char lowestDegree = gradeTable[sizeof(gradeTable)/sizeof(gradeTable[0]) - 1];
// 这里可用二分查找优化
while (gradeTable[gradeLevel] != lowestDegree) {
if(score < downLimit[gradeLevel]) {
++ gradeLevel;
} else {
break;
}
}
return gradeTable[gradeLevel];
}
将来如果等级规则变了(比如 85~100 分为等级 A,或添加 50~60 分为等级 E),只需要修改 gradeTable 和 downLimit 表(也可通过配置文件形式)就行,degree 函数可以保持一行都不改动。


浙公网安备 33010602011771号