我在尝试设计一些通用存储时遇到了问题..
基本上我有以下4个对象
托盘 框 包 项目
前3个是所有容器,其中可以包含比自身更低的任何容器。 最初,它被迫使托盘包含盒子,盒子包含包裹,包裹包含物品。 但现在我想要它,所以可以跳过一些'中间'容器: EG,托盘包含包含物品的包裹(无纸箱) EG2,托盘包含物品(无纸箱或物品)。
目前,我为每个对象都有一个数据库表。 但是设计一种跟踪所有事物的方法变得一团糟。
在Code中,我遇到了其他问题,例如打印托盘的内容,最初是:
class Pallet : List<Box> {}
class Box : List<Parcel> {}
class Parcel : List<Item> {}
class Item {}
class Pallet : List<Box>
{
void Print()
{
foreach (Box b in this)
foreach (Parcel p in b)
foreach (Item i in p)
//Print
}
}
但是既然我不知道里面会是什么,我不知道该如何去做。
我希望有人可以就设计好的数据结构或以良好有效的方式存储所有内容的方法给我建议。 我可以做类似的事情:
class Pallet : List<T>
{
void Print()
{
if (this[0] is Box)
//do this
if (this[0] is Parcel)
//do this, etc
}
}
但它似乎非常混乱。
我希望你能看到我想要做的事情。
答案 0 :(得分:2)
为什么不能简单地从完全相同的基类派生每个容器?然后你可以得到以下内容:
public abstract class Container
{
public abstract void Print();
public List<Container> Contents { get; set; }
}
public class Box : Container
{
public override void Print()
{
foreach (Container c in Contents)
Console.WriteLine("I am a {0}", c.ToString());
}
}
这意味着任何容器都可以包含许多其他容器。当然你需要实现一些逻辑来控制它,你不希望Box包含太多的Parcel,但是Box可以包含另一个盒子,只要它更小。现在你会说“但是Item也必须继承COntainer才能包含在Box中”,你会是对的,但你仍然可以使用继承和一个简单的小改动:
public interface IContainable { }
public abstract class Container
{
public virtual void Print()
{
foreach (IContainable c in Contents)
Console.WriteLine("I am a {0}", c.ToString());
}
public List<IContainable> Contents { get; set; }
}
public class Pallet : Container { }
public class Box : Container, IContainable { }
public class Item : IContainable { }
使用此方法意味着Pallet
可以包含内容,但不能包含它。可以包含Item
但不是容器。
您还可以将所有容器存储在同一个自引用数据库表中 - 它们不需要分开。每个包含的项都可以简单地将一个foriegn键返回到同一个表中作为其容器的另一个条目。
答案 1 :(得分:1)
但现在我想要它,所以可以跳过一些'中间'容器
我会重新考虑这一点。它看起来很简单,但基本上你在这里创建第二个并行的数据结构。它引入了一组全新的约束。
最好的“解决方法”可能是为每个托盘提供默认(无名)框等。
答案 2 :(得分:1)
在我看来,你已经迈出了一步,实际上让你的设计变得更糟。我会建议你回到你原来的包含盒子等的托盘的约束,但稍作修改。
如果您将一个包裹添加到托盘,请创建一个“虚拟”框以将其放入,并使用一个属性来指示它是一个“虚拟”实体。
然后,您可以保留现有的,整洁的结构。但也增加了灵活性。