私は倉庫の自動化で、次のタスクのドメインモデルを作成しようとしています。インターフェイスで抽象度のレベルを分離するにはどうすればよいですか?
倉庫には多くの製品があります。製品は、液体または食料品、または部分ごとにすることができます。倉庫には、液体製品または他のすべての製品を梱包する2つの梱包ラインがあります。ピース・バイ・パーツ・プロダクトはパッキングを必要としません。ここで
は私のモデルは以下のとおりです。
enum ProductType
{
Liquid,
Grossery
}
interface IProduct
{
ProductType ProductType { get; }
}
interface IPackedProduct : IProduct
{
bool IsPacked { get; }
}
interface ILiquidProduct : IProduct
{
}
interface IGrosseryProduct : IProduct
{
}
interface IPackingLine
{
IPackedProduct Pack(IProduct product);
}
interface IGrosseryPackingLine : IPackingLine
{
IPackedProduct Pack(IGrosseryProduct p);
}
class ProductPackingLine : IPackingLine
{
public IPackedProduct Pack(IProduct product)
{
Console.WriteLine("Packing {0} default packing line", product);
return new PackedProduct(product);
}
}
class LiquidsPackingLine : IPackingLine
{
public IPackedProduct Pack(ILiquidProduct product) // I want this <=======================
{
Console.WriteLine("Packing {0} by liquid packing line", product);
return new PackedProduct(product);
}
}
class GrosseryPackingLine : IPackingLine
{
public IPackedProduct Pack(IProduct product)
{
Console.WriteLine("Packing {0} by grossery packing line", product);
return new PackedProduct(product);
}
}
私はこのようにそれを使用しています:ここで
IProduct milk = new LiquidProduct(ProductType.Liquid);
IProduct pasta = new GrosseryProduct(ProductType.Grossery);
var packer = new PackingManager();
IPackedProduct packedMilk = packer.Pack(milk);
IPackedProduct packedPasta = packer.Pack(pasta);
はPackingManager
class PackingManager
{
public IPackedProduct Pack(IProduct product)
{
IPackingLine pl = GetPackingLineByProduct(product);
return pl.Pack(product);
}
private IPackingLine GetPackingLineByProduct(IProduct product)
{
switch (product.ProductType)
{
case ProductType.Liquid:
return new LiquidsPackingLine();
case ProductType.Grossery:
return new GrosseryPackingLine();
default:
throw new InvalidOperationException();
}
}
}
ある問題がI'LL場合ということですIPackingLine.Pack(IProduct p)
ILiquidProduct
のオブジェクトを誤って間違った梱包ラインに渡すことができます。しかし、より普遍的な方法でそれらを使用できるようにするには、すべての包装ラインをIPackingLine
に実装する必要があります。
これを回避するにはどうすればよいですか?
ジェネリックスを使用する必要があるようですので、特定のパッカーがパックできる種類のものを修飾することができます。言語を推測します(例: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/introduction-to-generics – jonrsharpe
あなたの 'PackingManager'は、Open Close Principleを破ります。なぜ汎用/一般的な 'PackingManager'が必要ですか? –
私は、使用する梱包ラインを決定する人が必要です。それ以外の場合、ロジックはアプリケーション全体に広がります。 'GetPackLineByProduct'に関してはここは簡単にするためのものです。実際のアプリケーションでは、私は 'IPackingLine'を構築するファクトリを挿入します –