我有一个域对象Invoice
,它有大约60个属性,有些是必需的,有些是可选的。此Invoice
类表示基础数据库表中的记录,其中某些列值包含应用程序层类(如存储在DB中的简单整数的枚举,双精度货币等)。
此Invoice
类目前定义如下:
现在,它正在吓唬这个创建Invoice
对象的类的客户端,将所有60个奇数属性传递给构造函数。我坚决反对以明显的理由制作 public 。
您能否建议一种更好的方法来允许创建/修改此发票对象?如果您需要更多详细信息,请与我们联系。
答案 0 :(得分:18)
使用Joshua Bloch在他的书Builder Pattern中描述的Effective Java 2nd Edition。您可以在http://www.javaspecialists.eu/archive/Issue163.html
中找到相同的示例特别注意这一行:
NutritionFacts locoCola = new NutritionFacts.Builder(240, 8) // Mandatory
.sodium(30) // Optional
.carbohydrate(28) // Optional
.build();
BeansUtils.populate
其他方法是使用org.apache.commons.beanutils.BeanUtils.populate(Object, Map)
中的方法Apache Commons BeansUtils。在这种情况下,您需要一个地图来存储对象的属性。
<强>代码强>:
public static void main(String[] args) throws Exception {
Map<String, Object> map = new HashMap<>();
map.put("servingSize", 10);
map.put("servings", 2);
map.put("calories", 1000);
map.put("fat", 1);
// Create the object
NutritionFacts bean = new NutritionFacts();
// Populate with the map properties
BeanUtils.populate(bean, map);
System.out.println(ToStringBuilder.reflectionToString(bean,
ToStringStyle.MULTI_LINE_STYLE));
}
<强>输出强>:
NutritionFacts@188d2ae[
servingSize=10
servings=2
calories=1000
fat=1
sodium=<null>
carbohydrate=<null>
]
答案 1 :(得分:4)
你可以做的可能是decompose你的对象变成较小的对象。根据上面的注释,您可能需要用户构建这些新对象,但是,根据您的数据库设计,您可能只需要将主键或外键传递给该类。
然后,该类将具有一些行为,它将从数据库中搜索相关数据。这显然会增加数据库服务器的负载,但它会使您的类更简单(尽管数量更多)。复杂性的降低很可能会增加代码重用性的可能性,并使其更易于维护。
答案 2 :(得分:0)
正如@Jake King的建议,将60个属性组合成更小的数据对象总是更好。
在这样做时,我将研究一个方面,可能的组合是可选的,我将以这种方式组成。例如,如果客户端点击表示使用当前地址和邮寄地址,则邮件地址是可选的。
围绕这些组合对象构建构造函数将帮助您轻松有效地管理/维护类。
答案 3 :(得分:-3)
如果您的发票对象有60个属性,并且您确定不需要其中一些属性,则不需要为这些属性创建getter和setter。始终建议您创建在代码中需要的属性的getter setter 。但是你需要确保省略的字段应该允许数据库中的空约束。
否则,如果您需要代码中的所有60个属性,则根据客户端的要求创建不同的构造函数。如果客户端只需传递4然后创建接受4个参数的构造函数,则可以为数据库中的属性设置默认值值不会被客户传递。