我想设计形状类。我需要区分几种不同的形状:
-Point
-Line
-Triangle
-Circle
-Polygons 这个类的主要目的是计算两个形状之间的距离。
我有计算这些距离的所有方法,但我想要一个可以使用的方法,它应该是这样的:
float Distance(Shape a, Shape b)要做到这一点,最简单的方法是放入大量的if语句,然后调用适当的方法,但这显然不是OOP。
如何在OOP风格中设计这样的类?
发布于 2010-04-11 04:00:56
这是一个棘手的问题,因为如果您正在实现使用最近点计算两个对象之间的距离的方法,那么您确实需要知道这两个对象的类型。例如,如果您使用中心点来比较它,那么它将很容易-您只需添加GetCenter方法,但这在这种情况下根本不起作用。
问题是,如果您可以将类层次结构设计为可扩展的,那么类层次结构就很有用-也就是说,允许在不修改现有类型的情况下添加其他类型。这里不是这种情况,因为当您添加Ellipse时,您将需要实现DistancePointEllipse、DistanceTriangleEllipse等...使用函数式语言中已知的algebraic data type来表示这一点会容易得多。例如在F#中:
type Shape =
| Circle of float * float * float // center & radius
| Point of float * float // center然后,您可以使用模式匹配来处理所有可能的情况:
match shape1, shape2 with
| Circle(x1, y1, r1), Circle(x2, y2, r2) -> // two circles
| Point(x1, y1), Point(x2, y2) -> // two points
| Circle(cx, cy, r), Point(px, py)
| Point(px, py), Circle(cx, cy, r) ->
// point and a circle (both combinations函数式编程似乎更适合这个问题:-)。
无论如何,一种可能的(但仍然是不可扩展的)面向对象设计是让Shape基类具有DistanceToPoint、DistanceToTriangle等方法,这些方法计算从当前类型到另一种形状类型的距离(因为您确实需要所有的组合)。
另一种方法是简单地在C#中编写重载方法:
float Distance(Triangle t, Point p);
float Distance(Triangle t, Circle c);
// ... etc这个选项的好处是,您可以很容易地减少需要编写的方法的数量。例如,如果您有一个用于Ellipse和Point的案例,则可以从Ellipse继承Circle,然后在比较Circle和Point时也使用现有案例。
发布于 2010-04-11 03:16:59
这取决于你对“距离”的定义。您可以为基类提供一个抽象的CenterPoint属性,该属性被每个派生类覆盖。现在很简单了。
发布于 2010-04-11 04:39:09
一种可以使其可扩展的设计是将距离查找封装为对特定形状进行操作的策略。您将为新的形状类型对注册委托,然后系统可以使用这些委托来解析任何形状类型对的适当函数。这将允许可扩展性,但它也会增加复杂性并降低性能。如果您的层次结构如您所描述的那样简单,那么简单的条件语句将会更快、更容易维护。
这里真正的问题是,所讨论的函数不是特定类的简单行为,而是涉及系统中所有形状的知识。对于'OOP‘,你能做的最好的事情就是把所有混乱的条件都封装在一个知道你所有形状的管理器类中。您无法避免由于提供此功能而引入的必要耦合,但您至少可以将其隐藏在一个更简单的接口后面,正如您所描述的那样。
https://stackoverflow.com/questions/2614589
复制相似问题