3

我需要进行复杂的计算。在我的例子中,创建一个 Calculator 类(使用策略模式抽象)似乎是最自然的。

为了执行计算,该类需要接受大约 20 个输入,其中一些是可选的,其中一些可能在未来发生变化等。一旦调用了Calculate()方法,大约需要输出 20 个不同的变量。

有多种方法可以实现这一目标。

  • 作为参数传入计算方法的输入
  • 通过计算器的属性传入的输入
  • 输入封装到它们自己的类中,然后传递给Calculate() 方法。
  • 计算()返回的输出,封装在一个类中
  • 填充到传递给 Calculate() 方法的参数中的输出
  • 在调用 Calculate() 之后从 Calculator 的公共属性中检索的输出

所有这些方法都有优点和缺点。你会怎么做?

更新:感谢您的反馈。

此计算器的目的是生成报价。输入是客户地址、利率、目标利润、附加费用、产品 ID 等内容,输出包括报价、实际利润、更多费用等。

我已经创建了 ICalculateInput 和 ICalculateOutput 接口及其具体类,现在系统运行良好。Calculator 类还继承自 ICalculator 接口(因为所涉及的计算因产品来源的公司而异)。

4

10 回答 10

4

我会推荐

  • 输入封装到它们自己的类中,然后传递给Calculate() 方法。
  • 计算()返回的输出,封装在一个类中

仅当您进行多步计算,或者基本计算步骤可能多次完成并且很难重新填充输入时,才在计算器中存储状态才有意义。否则,当您对它进行多线程处理或在代码的不同部分重用相同的对象时,这是一个糟糕的抽象。

有很多参数很难维护和阅读,如果你需要改变一些东西是不灵活的

改变参数以生成输出是一个坏主意。从调用者的角度来看,他“拥有”的类已通过将其传递给函数而被更改,这一点并不明显。

于 2008-12-08T22:35:19.143 回答
3

大多数人建议使用“参数类”和“结果类”。我同意这种方法,但在我看来,您的参数分为几类。也许您可以为必需参数创建一个参数类,并为可选参数或可选参数组创建一个单独的参数类。这样,您可以根据需要的计算类型创建不同的方法;

Result calculate(RequiredArgs requiredArgs) {
...
}

Result calculate(RequiredArgs requiredArgs, OptionalArgs optionalArgs) {
}

Result calculate(RequiredArgs requiredArgs, OptionalArgs optionalArgs, OtherOptionalArgs oOpitonalArgs) {
}

这将使您的 API 更易于使用。如果您不想为不同的组创建类,您也可以使用 Maps,但这需要计算引擎中的更多验证代码。通常我更喜欢参数类,但必须更多地了解您的特定问题才能做出决定。

由于线程安全和对象可重用性,我不会将计算结果存储在计算引擎本身中。维护无状态的代码要容易得多。

于 2008-12-08T23:11:56.463 回答
1

长参数列表变得繁琐且容易出错。告诉我们更多关于应用程序和环境的信息,但一般来说,传递某个类的对象或使用列表等会很诱人。

我已经完成的一种相当不错的处理方法是使用复合模式。例如,在 Java 中,您可以创建一个 Parameter 接口,然后创建一个实现 Parameter 的对象列表。

于 2008-12-08T22:35:01.467 回答
1

根据经验,不要创建接受超过 3-4 个单独参数的方法

在 JavaScript 中你不应该做的事情:

var addUser = function (name,surname, age, add1, add2, telephone) {
    //do something
};

而不是上面的,它最好做这样的事情:

var addUser = function (userDetails) {
    //Do something with userDetails.name etc...
};
//Then invoke the function by passing in an object:
var ud = {name : 'Andreas', surname : 'Grech', age : 20, add1 : 'bla', add2 : 'bla', telephone : 12343}; 
addUser(ud);

这样,您可以通过按您喜欢的任何顺序输入参数来调用该函数而不会破坏它,您甚至可以跳过一些

于 2008-12-08T22:35:32.807 回答
1

我同意您的输入和输出应包含在它们自己的类中。

如果部分或所有参数是可选的,您可能要考虑的一种可能性是使用Builder 模式来构造输入对象。

于 2008-12-08T23:31:39.123 回答
1

你漏掉了

  • 放入字典中的输入,该字典被传递给计算

有人想知道为什么一个函数有 20 个输入……似乎过多。但是,如果您需要它们,并且有些是可选的,并且将来可能通过策略模式更改计算方法,那么传入命名变量的集合可能是有意义的。您甚至可以在集合中指定策略模式,以便计算方法是完全通用的

于 2008-12-10T00:32:18.797 回答
0

你没有提到语言,但我会假设 c#。我可能会将它们作为结构(或类)传递并以相同的方式返回输出。

或者,我会找到一些方法来重构它并简化预期的输入/输出。

于 2008-12-08T22:30:31.023 回答
0

尝试做 .net 中的数据库提供程序类所做的事情。

有一个参数类(具有方向的类型和值属性,即输入/输出)并有一个参数(参数的集合)作为计算器的属性。

有关详细信息,请查看 .net 中用于调用存储过程/函数的 OleDBCommand/SQLCommand 类。

于 2008-12-08T22:32:39.413 回答
0

就个人而言,我会创建一个自定义输入和输出结构或类,并预先填充它们,将它们传入,并接收输出结构或类的返回值。

于 2008-12-08T22:34:52.170 回答
0

假设您已经认真考虑过并确定,是的,您确实需要所有这些参数:

我很可能会使用命名参数,但我选择的语言 (Perl) 支持与顺序无关的命名参数。如果你没有,那么传入一个对象是下一个最佳选择。必须以特定顺序(命名或不命名)传递超过 2-3 个参数只是自找麻烦。

对于输出,如果返回的值不止一个,我很可能会返回一个对象。

于 2008-12-10T01:25:02.747 回答