首页 > 代码库 > 8.3.2 构建组合行为
8.3.2 构建组合行为
8.3.2 构建组合行为
在清单 8.11 中,检查和报告验证最低收入和最小当前工作年限的函数,明显重复。这些检查有类似的结构:都检查客户的某一属性是否小于最小的允许值。
找出共性是只删除重复第一步,下一步是要看 checkJobYears 和 checkIncome 函数(连同其报表函数)的哪部分是不同的:
■ 检查不同的属性。
■ 使用不同的最小值。
■ 有略微不同的消息。
要写出更简洁的代码,我们可以创建一个函数,把这三个不同的部分作为参数,返回 ClientTest 记录。当我们创建检查列表时,用不同的参数值调用新的函数两次,就创建两个类似的检查。清单 8.13 显示额外的函数(lessThanTest),以及创建检查列表的新方法。
清单 8.13 用一个函数创建类似的检查 (F# Interactive)
> let lessThanTest readFunc minValuepropertyName =
let report client= |
printfn "Checking ‘%s‘ of ‘%s‘ failed (less than %d)!" | [1]
propertyName client.Name minValue |
{ Check = (funclient -> readFunc(client) < minValue) [2]
Report =report };;
val lessThanTest : (Client -> int) ->int -> string –> ClientTest [3]
> let tests =
[ (lessThanTest(fun client -> client.Income) 30000 "income") | 创建两个相似的
(lessThanTest (fun client -> client.YearsInJob) | 有报表的测试
2 "years in the job") |
(* more tests... *) ];;
val tests : ClientTest list
像往常一样,类型签名[3]能提供关于这个函数的很多信息。LessThanTest 函数返回值为 ClientTest 类型,它包含了检查和报表函数。检查用三个参数生成的:
1 读客户的数字属性
2 指定必需的最小值(在本例中,表示收入或年数)
3 描述属性(用于报表)
代码首先声明一个嵌套函数report[1],参数为客户,输出检查未通过的原因。这个函数还使用 lessThanTest 函数的参数,因此,当 report 作为结果的一部分返回时,所有的这些参数将捕获在闭包中。当构建将返回的记录值时[2],我们指定 report 作为一个函数值,另一个函数是内嵌的 lambda 函数。
在函数式编程中,使用函数的元组或记录,很常见,它反映了 F# 的开发风格。但在 C# 中,我们使用不同的方法来实现这个示例。现在,我们要看一下开发过程,还要考虑如何用 C# 实现这个示例,并改善当前的F# 版本。
8.3.2 构建组合行为