我有一个包含大约40个属性(所有值类型)的类型,它代表我的业务的一种交易。此类的实例对应于我的数据库中的一行。我想保持我的类不可变,因为它只会用于读取操作,但我不知道如何在初始化期间设置40个属性。
通常我对不可变类型使用构造函数初始化,但我想避免编写带有40个参数的构造函数。我的房产的安装人员目前是私人的,但我愿意以足够的理由改变。是否有一种常见的方法来处理这种情况或更好的方法来解决问题?
答案 0 :(得分:10)
你的问题不是一个有40个参数的构造函数,而是一个有40个字段的类。
我建议打破这个。是否有任何相关领域?如果是这样,将它们分组到一个公共对象(例如EmailInfo),然后让你的大对象引用分组对象。
// Instead of this:
foo.EmailHeader
foo.EmailSubject
foo.Email...
// Do this:
foo.Email.Header
foo.Email.Subject
一旦你的类具有较少的直接属性,创建一个获取那些分组对象的构造函数并不是那么糟糕。
答案 1 :(得分:8)
快点。你提到你对象的setter是私有的。如果是这种情况,那么您的对象不是不可变的(否则setter不存在)。最好你的对象是只读的。
对于一个真正的不可变对象,别无选择,只能让构造函数接受初始化对象所需的所有值。减少构造函数中参数数量的最佳方法是将值分组为更大的对象,然后将这些对象传递给构造函数。虽然我不会这样做,除非这些值在逻辑上是相关的。
如果你的不可变类型确实需要40个值而且它们不相关,那么最好的方法是使用40个值的构造函数。那还是进一步打破了大不可变对象。
答案 2 :(得分:4)
我喜欢使用可变对象来实例化不可变对象的方法;可变对象只是为了整理选项。 .NET框架中的一个例子是ProcessStartInfo。
class XInfo {
public int A;
public int B;
}
class X {
public X (XInfo i) {
// you can transform the data/layout from i any way you need
..
}
}
new X(new XInfo() {
A = 42
})
虽然我会对'40个属性'保持不变,但我发现上述方法效果很好。额外的好处是XInfo
,X
中使用的内部结构可能完全不同,只要您能提供合理的映射。
答案 3 :(得分:1)
如果我按照你的说法“但我不确定如何在初始化期间设置40个属性。”,您的问题似乎是一个具有太多字段/属性的类。 似乎不是让它变成不可变的问题,因为你已经知道如何做到这一点。
我建议(和其他人一样),Refactor和Extract Class。
答案 4 :(得分:0)
作为替代方案,您可以使您的课程来自freezable,我认为这可能是您要搜索的解决方案。您可以对对象进行Instatiate,设置值,然后将其设置为冻结。一旦你将它设置为冻结,该类就是“只读”。
答案 5 :(得分:0)
我建议将参数放入一个或多个结构中,并让对象保存这些结构。嵌套对象是可能的,但会比嵌套结构增加更多的开销。
作为替代方案,您可以使用所有属性的“readonly mustoverride”版本创建一个抽象基类。由此,派生出一个可变且不可变的对象类。不可变的可以在其构造函数中接受基类,并使用所有readonly属性来构建新对象。可变类可以提供一种使用方法编写属性的方法,使用不同名称的读写属性来读取只读版本等。