在“假设”工具中使用实例时,不可变类是否合适?

时间:2011-03-17 18:20:14

标签: c# design-patterns immutability

我有一个基本上代表模型参数的类,并封装逻辑以使用这些参数计算模型的值。我正在尝试决定这个类是否应该是不可变的。在实践中,模型的实例将通过拟合到某些数据集来生成,因此从这个意义上来说(至少对我来说)该实例是不可变的,因为它与外部数据相关联。

另一方面,将有一个GUI让用户进行“假设分析”,其中他们可以更改参数以查看它如何更改模型值。所以我可以使模型变得容易,或者每次更改参数时创建新的副本。后者似乎很尴尬,特别是如果有例如可以单独上下调整的5个参数......似乎我必须为每个返回副本的参数实现一个SetX()方法,对吗?

我是否过度思考这个问题,还是有适当的模式在这里使用? (这是C#代码,但我猜不是特定于语言的)

3 个答案:

答案 0 :(得分:3)

仔细考虑该对象将如何实际用于您的推测分析。对于直截了当的,一次性的,让我们变异的领域 - 尝试 - 改变 - 改变它的场景,当然,只是让它变得可变。但是假设你想拔出大枪;那么拥有一个不可变模型会变得更好。

Data d = whatever;
// What if we mutate X and Y? Which one maximizes the value of Foo(d) ?
var query = from x in Range(0, 100)
            from y in Range(0, 100)
            let mutated = data.MutateX(x).MutateY(y)
            orderby Foo(mutated)
            select mutated;

var max = query.First();

等等。使用不可变模式,编写推测查询变得更加容易,可以更轻松地跨多个核心并行化这些查询,等等。

答案 1 :(得分:1)

  

后者似乎很尴尬

那是你的答案。 API设计的目标是使编写代码尽可能简单。如果特定模式使其比替代方案更难或更难,替代方案可能是正确的。

答案 2 :(得分:0)

我认为你可能会过度思考这一点。虽然可能有一个非常优雅的设计模式,它使用八个类和四个接口,我认为最简单的路线是使它成为一个普通的,可变的类。想想你的意图:你想要一个可以从外部数据加载的模型(可能是一个返回Model实例的静态方法),其参数可以根据用户输入而改变。这似乎是您日常花园品种的一个用例。

您也可以选择将您的类分成一个Data类和Strategy类,第二个包含可更改的参数,并使用类似策略模式来计算结果。