8.2.2.1 在 C# 中使用命令模式捕获状态
正如我们所解释的,命令模式经常使用可变状态,封装在某些对象中,像在我们例子中的 Receiver 类。清单 8.6 展示了这样的例子,为我们财务应用程序,创建了非常灵活的收入检查,目标是可以在以后配置检查,而不需要修改检查的集合。
清单 8.6 使用命令模式配置检查 (C#)
class IncomeTest { [1] <--对应 Receiver 组件
public int MinimalIncome { get; set;}
public IncomeTest() {
MinimalIncome =30000;
}
public bool TestIncome(Clientclient) {
return client.Income< MinimalIncome;
}
}
var incomeTest = new IncomeTest();
Func<Client, bool> command= | [2] 把 ConcreteCommand
client =>incomeTest.TestIncome(client); | 创建成函数
tests.Add(command) <-- 用Invoker 注册命令
我们首先创建一个有可变状态的类,对应于命令设计模式中的 Receiver 组件[1]。状态是建议最低收入,类有一个可变属性用来进行修改。接下来的方法实现了检查自身,并比较给定客户的收入是否比保存在检查中的当前最小值大。
清单 8.6 的另一个部分显示了如何能够新的检查。首先,我们创建 IncomeTest类的实例,它包含了状态;然后,再创建 lambda 函数,调用它的 TestIncome 方法[2]。这个函数对应于ConcreteCommand 组件,我们把它添加到检查集合中。我们已经用函数值替换了抽象的 Command 类型,所以,不需要实现接口,我们使用 lambda 函数语法,创建有适当类型的函数。清单 8.6 显式使用 lambda 函数语法,创建这个函数,演示了它对应的设计模式,但我们可以把它写更简洁:
IncomeTest incomeTest = newIncomeTest();
tests.Add(incomeTest.TestIncome);
C#编译器会自动创建委托实例,包装了 TestIncome 方法,如果该方法具有正确的签名,就能够加到集合中。一旦把检查添加到集合,就可以使用 MinimalIncome 属性来配置检查:
TestClient(tests, john);
incomeTest.MinimalIncome = 45000;
TestClient(tests, john);
(在第一行的结果是肯定的,在最后一行的结果是否定的。)
这是一种常见的模式,被广泛用在面向对象编程的命令式风格,从函数的观点看,应该谨慎使用:代码和注释应明确地归档,什么调用会影响可变状态。在示例中,状态使用 incomeTest 对象修改,这就解释了为什么同一行代码,在不同的时间调用,会得到不同的结果。在下一节,我们将看到如何使用 F#,以更简单的方式,实现类似的功能。