我很难弄清楚如何用我的对象模型来遵守开放/封闭原则。下面是一个相当人为的例子,但它应该有助于说明我的情况。
问题:
如何正确表示部分由其类型描述的 InventoryItem 实体,例如 InventoryItem 可以是 Box 或 Roll。
我将如何添加一个新的“罐”库存项目,而不必更改管理库存项目的各种聚合方法。
如何在没有强制转换的情况下调用类型特定的方法。例如:Roll 类型的 InventoryItem 可能具有仅与 Rolls 相关的方法。所以现在如果我在 StorageLocation 对象中使用选项 2,我需要这样做。
((Canister)InventoryItem).FillCanisterWithProduct()
示例有界上下文:
public class Inventory //Aggregate Root
{
private List<StorageLocation> storageLocations;
public IEnumerable<StorageLocation> StorageLocations => new
List<StorageLocation>();
public Inventory() { }
}
public class StorageLocation
{
public string StorageLocationId { get; private set; }
/* Option 1 */
private List<Box> boxes;
public IEnumerable<Box> Boxes => new List<Box>();
private List<Roll> rolls;
public IEnumerable<Roll> Rolls => new List<Roll>();
private List<Canister> canisters;
public IEnumerable<Canister> Canisters => new List<Canister>();
/* Option 2 */
private List<IInventoryItem> inventoryItems;
public IEnumerable<IInventoryItem> InventoryItems => new List<IInventoryItem>();
public StorageLocation() { }
}
public class Box : InventoryItemBase
{
public float Length { get; set; }
public float Width { get; set; }
public float Height { get; set; }
public Box(int storageLocationId) : base(storageLocationId) { }
public override void CalculateStorageAreaRequired()
{
throw new NotImplementedException();
}
}
public class Roll : InventoryItemBase
{
public float Length { get; set; }
public float Width { get; set; }
public Roll(int storageLocationId) : base(storageLocationId) { }
public override void CalculateStorageAreaRequired()
{
throw new NotImplementedException();
}
}
public class Canister : InventoryItemBase
{
public float Height { get; set; }
public float Diameter { get; set; }
public float Gallons { get; set; }
public Canister(int storageLocationId) :
base(storageLocationId) { }
public override void CalculateStorageAreaRequired()
{
throw new NotImplementedException();
}
}
public abstract class InventoryItemBase : IInventoryItem
{
public string StorageLocationId { get; private set; }
public InventoryItemBase(int value) { }
public abstract void CalculateStorageAreaRequired();
}
public interface IInventoryItem
{
public string StorageLocationId { get; }
}