从单个对象inheritance的不同类型的集合与单个超级对象集合
想象一下以下场景。
class Shape { // methods of Class Shape } class Circle extends Shape { // methods of Class Shape // methods of Class Circle } class Square extends Shape { // methods of Class Shape // methods of Class Square } class Canvas // This class should a bucket of objects that belong to Square and Circle { // Declaring a single list of supertype List heterogeneousCollection; // Declaring two separate lists List homogeneousCollection; List homogeneousCollection; }
对应的关系模式如下
- 表格形状包含主信息
- Tables Circle&Square通过外键引用的方式丰富Shape中的数据(Circle& – Square是具有不同列的不相交集)
- Table Canvas是一种数据聚合
- Canvas加入Circle(1..n基数)
- Canvas加入Square(1..n基数)
哪种方法更好“声明单个超类型列表(异构集合)”或“声明两个单独的列表(两个不同的同类集合)”
在做出决定时,我正在考虑以下几点。
- 从数据库中读取时如何填充对象Canvas?
考虑一种避免N + 1问题并从单个查询中读取的方法
SELECT * FROM Canvas INNER JOIN Circle ON .. Canvas INNER JOIN Square ON .. Circle INNER JOIN Shape ON .. Square INNER JOIN Shape ON ..
现在,对于Canvas的每一条记录,我们最终得到(B + C)行。 但是,使用多个ORM工具,可以将Circle和Square中的组不同数据集分成两个单独的列表。 (我在这里考虑iBatis)
-
我们如何处理这些对象的几个函数?
对我们计划处理UIfunction以在对象Canvas中显示数据的情况进行成像。 除了Circle和Square之间的常用function,它们中的每一个都可以具有不同的function。 例如,Square可以有getLengthOfSide(),而Circle可以有getRadius()。 如果我们使用异构列表,我们最终可能会在需要访问这些函数的每个地方使用强制转换运算符。Class Canvas { void drawAll() { for (Shape s : heterogeneousCollection) { if (s instanceof Circle) { s.draw(); // common function present in Shape also s.xyz(); // specific to Circle } if (s instanceof Square) { s.draw(); // common function present in Shape also s.abc(); // specific to Square } } } }
在两个同类列表的情况下,我们可能分别为每个列表分别有两个不同的for循环。
但是,如果我们需要添加一种新的形状(例如三角形),它会影响Canvas,我觉得这是设计缺陷的结果,Java可能会配备这个来解决这个问题。 请注意这一点。 任何书籍/链接的参考都会有很大的帮助。 只是想告诉你们这不是学校的任务,我正在认真考虑各种解决方案。 请原谅我一个长期的问题。
PS:另一个解决方案List
List
被排除,因为我们无法在此集合中插入任何对象。
假设有许多地方您需要独立处理Circle和Square处理,我会通过应用访问者模式来处理异构集合
这样做的好处是,如果你以后添加Triangle,那么当你添加一个方法T visitTriangle(Triangle triangle);
对于访问者,在更新每个访问者之前,您的代码将无法编译,从而避免了令人讨厌的运行时意外情况。
但是……如果你真的只是在谈论处理Circle和Square的单个实例,那么在这里应用Visitor是过度的,我会考虑为doSomeSpecificUiThing()
添加一个抽象方法到Shape。
它看起来像这样:
class ShapeVisitor { T visitCircle(Circle circle); T visitSquare(Square square); } class Shape { abstract T accept(ShapeVisitor visitor); // methods of Class Shape } class Circle extends Shape { T accept(ShapeVisitor visitor) { return visitor.visitCircle(this); } // methods of Class Circle } class Square extends Shape { T accept(ShapeVisitor visitor) { return visitor.visitSquare(this); } // methods of Class Square } Class Canvas { void drawAll() { for (Shape s : heterogeneousCollection) { s.draw(); s.accept(new ShapeVisitor() { @Override Void visitCircle(Circle circle) { circle.xyz(); return null; } @Override Void visitSquare(Square square) { square.abc(); return null; } } } } }
当我们掌握一般信息而不是具体事实时,很难给出解决方案。 例如,xyz()和abc()方法。 他们是什么,为什么? 在你的例子中,它们似乎有类似的用法,所以我考虑在Shape中定义一个名为doSomethingSpecific()的抽象方法,以便它将由所有Shape子类实现。 现在你的代码是:
void drawAll() { for (Shape s : heterogeneousCollection) { s.draw(); // common function present in Shape also s.doSomethingSpecific(); // specific to each implementation } }
我尽可能喜欢异构集合。 我非常不喜欢instanceof
因为你指出的原因 – 当我们添加Triangle
时会发生什么。