我正在处理一个复杂的数据模型,在这个模型中,我们有不同的类,这些类有很多属性,我们有时需要比较或部分复制这些属性。然而,我们不能将它们集中在一个类中,因为它们中的一些是重叠的。
为了让您更好地理解,让我们举个例子:
public class Product {
private Amount price;
private String name;
private String description;
private Color color;
private Shape shape;
private Picture mainPicture;
private Company designer;
private Company maker;
}让我们假设生产是外包的,我们有时需要复制除maker之外的所有内容:
public Product copyForOutsourcing(Product product) {
Product p = new Product();
p.setPrice(product.getPrice());
p.setName(product.getName());
p.setDescription(product.getDescription());
p.setColor(product.getColor());
p.setShape(product.setShape());
p.setMainPicture(product.getMainPicture());
p.setDesigner(product.getDesigner());
return p;
}现在让我们假设产品以多种形式存在,有时我们需要复制除形状、颜色和图片之外的所有内容:
public Product copyForDeclension(Product product) {
Product p = new Product();
p.setPrice(product.getPrice());
p.setName(product.getName());
p.setDescription(product.getDescription());
p.setDesigner(product.getDesigner());
p.setMaker(product.getMaker());
return p;
}同样,我们需要不同的比较: p1.get*().equals(p2.get*())。正如你所看到的,它有点多余,当有更多的属性和/或更多的复制或比较方法时,它仍然是最糟糕的。此外,在添加属性时,我们总是忘记在copy和compare方法中添加它。
我们得到的第一个想法是添加注释:
@Outsourcing, @Declension
private Amount price;
@Outsourcing, @Declension
private String name;
@Outsourcing, @Declension
private String description;
@Outsourcing, @Declension
private Color color;
@Outsourcing
private Shape shape;
@Outsourcing
private Picture mainPicture;
@Outsourcing
private Company designer;
@Declension
private Company maker;这样,使用反射比较或复制属性很容易,没有多余的代码,并且在添加属性时,很容易更新复制和比较方法:我们只需向新属性添加注释。
但是,如果Product扩展了另一个类,比如CompanyObject,应该在copyForDeclension中复制"stockingLocations“这样的属性,会发生什么呢?CompanyObject不应该依赖于注释解密,因为这个注释是特定于产品的。CompanyObject甚至可能在其他项目中,因此无法修改。
如果我们想要使用反射来避免冗余,那么我们需要指定复制哪些属性:
public List<Field> getDeclensionAttributes() {
List<Field> list = new ArrayList<Field>();
list.add(ReflectUtils.getField(CompanyObject.class, "stockingLocation"));
list.add(ReflectUtils.getField(Product.class, "price"));
...
return list;
}问题是,通过这种方式,我们将属性名称指定为字符串,因此重构可能会破坏代码,编译器也不会警告我们!
所以问题是:当一个具有许多属性的类需要指定几个复制/比较方法时,实现这些复制和比较方法的最优雅的方法是什么?此外,如何确保添加属性会迫使开发人员质疑该属性在不同复制/比较方法中的行为?
发布于 2015-12-31 19:45:51
您可能只有一个复制实现,并通过传递要复制的属性列表(Enum表示属性列表)来控制要复制的属性。像这样的东西
public Product copyForDeclension(Product product, List<ProductAttributes> attribuitesToCopy) {
attribuitesToCopy.stream().forEach(productAttribute -> {
switch (productAttribute) {
case PRICE:
//do copy
break;
case NAME:
//do copy
break;
default:
// throw exception, will be helpful for maintain code
}
});
}
enum ProductAttributes {
PRICE,
NAME,
//.....
}这种方式的实现将是通用的和非冗余的,所有要考虑的属性将由copy的调用者处理(这对您的需求可能是好的,也可能是坏的)。
https://stackoverflow.com/questions/34545530
复制相似问题