对具有不同功能的相同 Java Class 进行数据建模的最佳方法

Best way to data model the same Java Class with different functionalities

案例:

通常产品对象具有这些属性:

  1. 名字
  2. 价格

但是在促销周期间,虽然大多数产品仍然只有名称和价格作为属性,一些 选定的产品获得了额外的属性:

但促销周过后,这些先前促销的产品将失去其颜色属性,重新成为标准产品。

当前实施:

我有 2 个 类 -> Product 和 ProductPromotion

public class Product {

    private String name;
    private BigDecimal price;
    private ProductPromotion promotion;

    public Product(String name, BigDecimal price) {
        this.name = name;
        this.price = price;
    }

    public void setProductPromotion(ProductPromotion promotion) {
        this.promotion = promotion;
    }
}


public class ProductPromotion {

    private Color color;

    public ProductPromotion (Color color) {
        this.color = color;
    }
}

如您所见,Product 单方面引用 ProductPromotion。默认产品对象对其 ProductPromotion 有一个空引用,而有促销的产品,我只是这样做:myproduct.setProductPromotion(new ProductPromotion(Color.RED));

每当我决定 myproduct 的促销活动结束时,我都会: myproduct.setProductPromotion(null);

我的问题:

我真的不喜欢每个非促销产品都有一个对 ProductPromotion 的空引用,因为这种建模不是很漂亮。我的意思是,如果占位符什么也没有(至少对于非促销产品而言),为什么我们需要保留占位符。因此,我想请教经验丰富的编码人员,以更好地实现此功能。

进一步思考:

根据你的意见和想法,我想出了一个新方法,我非常欢迎你对此的想法:

我会将 ProductPromotion class 拆分为默认版本和升级版本:

public class ProductPromotion {
    private boolean promotionDisabled;

    public ProductPromotion() {
        setPromotionDisabled(true);
    }

    public boolean isPromotionDisabled () {
        return promotionDisabled;
    }

    public boolean setPromotionDisabled (boolean value) {
        promotionDisabled = value;
    }
}

public class ProductPromotionEnabled extends ProductPromotion {
    private Color color;

    public ProductPromotion (Color color) {
        super(false);
        this.color = color;
    }

    public Color getColor () {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }
}

所以我会创建一个类型为 ProductPromotion 的 defaultPromotionObject,它引用了任何非提升的对象。而促销中的对象将指向 ProductPromotionEnabled 类型的 promotionEnabledObject。您对此有何看法?

A​​ class 定义实体的属性和行为。 当我们在 class 中放置私有 "ProductPromotion promotion" 属性时,这意味着所有产品都应该有促销,为了表明特定产品没有促销,我们在其中放置一个空值。

不应该是这样的。 实现此目的的更好方法是从 Product class 中删除 "private ProductPromotion promotion" 属性,ProductPromotion class 应重命名为 PromotedProduct。 PromotedProduct 应该从 Product 继承,因此它将是具有促销的特定类型的产品。

这样我们就有两个class了。 Product和PromotedProduct(特定类型的产品)然后我们可以使用多态性对产品列表进行操作。

代码:

public class Product {

    private String name;
    private BigDecimal price;

    public Product(String name, BigDecimal price) {
        this.name = name;
        this.price = price;
    }

}

public class PromotedProduct extends Product {

    private Color color;

    public PromotedProduct(String name, BigDecimal price ,Color color) {
        super(name ,price);
        this.color = color;
    }
}

Product product[3];
product[0] = new Product("keyboard",100);
product[1] = new PromotedProduct("stick", 80 ,Color.RED);

等等。

使用classOptional。这消除了 null 值,实际上您似乎想要这种关系。

private Optional<ProductPromotion> promotion = Optional.empty();

promotion.ifPresent(promo -> promo...);

另一种方法是将产品映射到促销活动。