我有一对现有的业务对象类型Product
和PurchasedProduct
,后者是前者的子类。
前者代表客户购物篮中的一个对象,所有信息(数量除外)都是从存储在数据库中的“原型”产品中读取的。
当客户结账时,购物篮的内容会以其原型的ID存储在数据库中,但所有相关的潜在可变购买信息(净价,增值税税率,数量等)都会被“烘焙”进入记录。这样,当客户检查他们的订单历史记录时,每个订单都会创建一个PurchasedProduct对象,该对象将报告at-checkout值,而不是原型值。
因此,在检索购买的产品实例时,可以首先读取原型以填充大部分数据(因为PurchasedProduct
是-a Product
),然后将购买的实例读取到填写at-checkout值。
现在客户希望产品“捆绑”。除了以下内容之外,它们在各方面都与单一的“产品”相同:
1)捆绑包含Product
个对象(具有固定数量)的列表,但其自身价格与所包含的产品,其自身数量等无关。
2)购买时,不仅要记录自己的结账时间价格等,还要记录其成分产品的价格
我最初的想法是:
ProductBundle : Product
{
public List<Product> Products { get; set; }
// other stuff as needed
}
PurchasedProductBundle : PurchasedProduct
{
public List<PurchasedProduct> Products { get; set; }
// other stuff as needed
}
这似乎给ProductRepository
增加了很多复杂性,PurchasedProductBundle
的职责主要是将产品ID转换为业务对象。它需要检查传入的数据,并在这四种类型中的每一种之间切换多个路径,其中一些路径具有重复的功能。它似乎也复制了子产品列表属性。最后,ProductBundle
既是PurchasedProduct
又是ProductBundle
,但C#当然没有多重继承。
替代路线可能是组合,因此Product
是单个Product
的组合和Product
的列表,但这似乎是很多传递属性的样板通过基础{{1}}进行访问。
这些都是合理的路线,还是我缺少一些非常简洁的模式?
答案 0 :(得分:1)
一种可能性是考虑PurchasedProduct
不是Product
来自IProduct
&#34;。而是拥有PurchasedProduct
界面,可以是Product
或IProductBundle
。
对于IProduct
和IEnumerable<IProduct> Products { get; set; }
,您的产品包将为PurchasedProductBundle
(ProductBundle
},并提供PurchasedProduct
。
背后的原因是Product
不一个Product
,它更像是购买或 OrderLine < / {>比{{1}},并且可能有很多原因可以用来改变价格,不仅价格会随着时间的推移而发展,还有商业报价,优惠券。
另一种可能性是考虑到你根本不介意捆绑产品的价格是多少?毕竟你可能会在全球范围内宣传回扣百分比,但这是另一个问题。