首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java中的几种克隆及其比较

java中的几种克隆及其比较
EN

Stack Overflow用户
提问于 2015-12-31 19:06:34
回答 1查看 44关注 0票数 0

我正在处理一个复杂的数据模型,在这个模型中,我们有不同的类,这些类有很多属性,我们有时需要比较或部分复制这些属性。然而,我们不能将它们集中在一个类中,因为它们中的一些是重叠的。

为了让您更好地理解,让我们举个例子:

代码语言:javascript
复制
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之外的所有内容:

代码语言:javascript
复制
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;
}

现在让我们假设产品以多种形式存在,有时我们需要复制除形状、颜色和图片之外的所有内容:

代码语言:javascript
复制
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方法中添加它。

我们得到的第一个想法是添加注释:

代码语言:javascript
复制
  @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甚至可能在其他项目中,因此无法修改。

如果我们想要使用反射来避免冗余,那么我们需要指定复制哪些属性:

代码语言:javascript
复制
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;
}

问题是,通过这种方式,我们将属性名称指定为字符串,因此重构可能会破坏代码,编译器也不会警告我们!

所以问题是:当一个具有许多属性的类需要指定几个复制/比较方法时,实现这些复制和比较方法的最优雅的方法是什么?此外,如何确保添加属性会迫使开发人员质疑该属性在不同复制/比较方法中的行为?

EN

回答 1

Stack Overflow用户

发布于 2015-12-31 19:45:51

您可能只有一个复制实现,并通过传递要复制的属性列表(Enum表示属性列表)来控制要复制的属性。像这样的东西

代码语言:javascript
复制
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的调用者处理(这对您的需求可能是好的,也可能是坏的)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34545530

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档