原来这就是表驱动开发

现在需要你提供这样一个函数:获得指定月份的天数(为了方便讨论,忽略闰年)。你会怎么做?
大概率是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
func DaysOfMonthGeneral(month int) int {
	switch month {
	case 1:
		return 31
	case 2:
		return 28
	case 3:
		return 31
	case 4:
		return 30
	case 5:
		return 31
	case 6:
		return 30
	case 7:
		return 31
	case 8:
		return 31
	case 9:
		return 30
	case 10:
		return 31
	case 11:
		return 30
	case 12:
		return 31
	default:
		panic("invalid month")
	}
}

表驱动开发则是这样的:

1
2
3
4
5
var daysPerMonth = []int{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

func DaysOfMonth(month int) int {
	return daysPerMonth[month-1]
}

这个例子太简单?那再看个例子。

根据分数得到等级。

分数 等级
>=90 A
<90 B
<75 C
<65 D
<50 F

你很可能会这么做:

1
2
3
4
5
6
7
8
9
10
11
12
13
func GetGradeGeneral(score float32) string {
	if score >= 90.0 {
		return "A"
	} else if score >= 75.0 {
		return "B"
	} else if score >= 65.0 {
		return "C"
	} else if score >= 50.0 {
		return "D"
	} else {
		return "F"
	}
}

有没有更灵活的方式呢?

有的,还是表驱动法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var (
	rangeUpper = []float32{50.0, 65.0, 75.0, 90.0, 100.0}
	grades     = []string{"F", "D", "C", "B", "A"}
)

// GetGrade 表驱动法
func GetGrade(score float32) string {
	maxGradeLevel := len(grades) - 1

	gradeLevel := 0
	studentGrade := "A"
	// 数据量大时可考虑二分查找
	for studentGrade == "A" && gradeLevel < maxGradeLevel {
		if score < rangeUpper[gradeLevel] {
			studentGrade = grades[gradeLevel]
		}
		gradeLevel++
	}
	return studentGrade
}

总结

表驱动,就是把复杂的条件分支或运算逻辑转移到对“表”的访问上。

这里说的“表”和数据库中的表没有关系,更像是一张表格或者容器。通常可以用数组或者Map实现。

加入讨论

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据