我正在开发 PIM 系统。有一个聚合根产品,它具有属性、产品类型(餐食、杂货)、名称、图像等。但正如您所知,一些产品类型(如药房)正在进入我们的系统。实际上;膳食和杂货产品的特性非常不同。
如果我在产品类(组合)中实现膳食和杂货复杂对象,则该模式显示适合 DDD 聚合根,但存在一个问题,即当药品产品进入我们的聚合时使用打开/关闭 prensiple
public class Product extends BaseAggregate<Long> {
private String description;
private Status status;
private Long categoryId;
private ArrayList<String> medias;
private Grocery Grocery;
private Meal Meal;
public Product(description,status,categoryId,...){
description=description;
...
}
public setStatusAsPassive(){ status=Status.Passive }
.... (Rich Model)....
}
如果我使用继承来实现,如下所示
public abstract class Product extends BaseAggregate<Long> {
private String description;
private Status status;
private Long categoryId;
public ArrayList<String> medias;
protected abstract Channel getChannel();
public Product(description,status,categoryId,...){
description=description;
...
}
public setStatusAsPassive(){ status=Status.Passive }
.... (Rich Model)....
}
public class GroceryProduct extends Product {
private Long brandId;
public Double desi;
public Weight weight;
public CatalogType catalogType;
public Catalog catalog; //?
private Boolean isAutoApprovable;
private String barcode;
@Override
protected Channel getChannel() {
return Channel.MEAL;
}
public GroceryProduct(description,status,categoryId,...){
super(description)
...
}
.... (Rich Model)....
}
public class MealProduct extends Product {
public Boolean ownSellable;
public Boolean upsellOffer;
public ProductType productType;
public Attribute attribute;
@Override
protected Channel getChannel() {
return Channel.MEAL;
}
public MealProduct(description,status,categoryId,...){
super(description)
...
}
.... (Rich Model)....
}
如果我通过继承实现聚合根,我该如何管理领域模型?正确吗? 这个实现似乎没有众所周知的战术 DDD、丰富域模型。尽管产品是聚合根,但丰富的领域模型和服务在杂货和餐饮模型方面在某些地方有所不同。即使我实现了单个产品存储库,我仍然可以控制使用餐食或杂货。
我应该使用哪种情况?继承与组合
如果膳食、杂货、药品完全不同,它们可能只是实体,也许 AggregateRoot 可能是订单(或购买)实体。
产品本身有什么行为吗?也许您希望使用抽象 Product 来扩展(或实现)实体,而不是 AggregateRoot。
聚合应该保护交易边界,因此尝试识别应用程序中进行的交易。
我认为包含不同产品的订单可能比单个产品本身更好地代表交易,并且最终具有相同行为的多个聚合根(另外,它们的交易行为是什么?)。
具体到你的问题:使用组合还是继承更多的是个人(技术)选择,因为最终只决定如何处理多态性和某些对象之间的引用;域名并不决定使用什么。
组合往往更冗长一些,但更灵活、可重构,不会将您与强大的隐式依赖关系联系在一起,并且它允许轻松安排移动部件的组合(如果您仍在探索建模,则特别有用)。
不要专注于技术实现,而是首先尝试确保您的 DDD 建模在您的领域行为方面是一致的、有凝聚力的和描述性的。
我有时强迫自己进行的一个很好的练习是,通过仅定义接口(关系和公共行为)来处理域,并跳过整个具体的抽象/类实现,直到我有一个清晰的域结构。这样可以轻松交换接口(实体、AR、VO),并根据您的最终领域/业务目的将重点放在首次建模上,从而排除所有技术细节或具体实现。