阶级关系:需要建筑咨询

时间:2014-10-15 14:57:00

标签: c++ design-patterns

假设我们有一些在它们之间有关系的类。作为示例,几何或数学库具有Vector3,Matrix4,Plane3..etc。它们之间有很多交叉测试方法。例如测试Plane3和Vector3之间的交集;如果Vector3(作为点)在平面上,在飞机外面和飞机前面......等等。

因此可以在Vector3和Plane3类上编写交集测试方法。但这会导致一个小问题,并重复硬编码。对于这种情况有什么建议。

  • 在一个具有更多含义的类上实现该方法,特别是在Plane3上,因为它更多地用于交叉点,其目的是,交叉测试和这类事物。
  • 在两个类上实现。
  • 在实用程序类中实现为静态方法。
  • 其他

第一种情况可能是好的,但有时候情况并不清楚。并且第二个需要更多重复的代码,因为许多类具有许多方法,导致代码的笛卡尔乘法增加。第三个可能是好的,但有时它不能访问私有或受保护的类方法(如果没有实现为朋友),我通常不知道如何对实用程序类进行分类,用户知道方法的位置会更加困难/她在找。对于这种情况有没有任何方法?

编辑:更详细的例子。

class A {}
class B {}
class C {}

首先:

bool A::IsIntersecting(const B& b) const;
bool A::IsIntersecting(const C& c) const;
bool B::IsIntersecting(const C& c) const;

第二

bool A::IsIntersecting(const B& b) const;
bool A::IsIntersecting(const C& c) const;
bool B::IsIntersecting(const A& a) const;
bool B::IsIntersecting(const C& c) const;
bool C::IsIntersecting(const A& a) const;
bool C::IsIntersecting(const B& b) const;

第三

bool IntersectUtility::IsIntersecting(const A &a, const B &b);
bool IntersectUtility::IsIntersecting(const A &a, const C &c);
bool IntersectUtility::IsIntersecting(const B &b, const C &c);

3 个答案:

答案 0 :(得分:1)

Implement the method on one class which has more meaning to has it, specically on Plane3 because it is used more for intersections, its aim is, intersection test and this kind of things.

这个解决方案“闻到”了我,原因有几个。我看到的最大问题是,当消费者试图找出特定几何对象的intersectionTest函数所在的位置时,它会非常混乱。例如,它是Line还是Point?如果LinePlane相交,请测试一下?我可以看到挑选任意规则的诱惑,比如高维对象包含对应于低维的函数,但是当你测试相同维度的对象时,你会遇到同样的问题,比如一个立方体和一个圈。

Implement on both classes.

这是重复的代码太多了。但是,您可以通过创建能够完成大部分工作的1D,2D,3D等基础实现来逃脱。这显然会利用继承,你说你不想这样做。

Implement in a utility class as a static method.

这没有一个明显的解决方案的原因是这些对象的两者(或更多,你似乎不想考虑)的交集并不真正属于少考虑一个物体与另一物体相交,而是根据它们在“空间”中的位置构建一个解决方案,无论是1D-在一天结束时,无论是将其实现为裸函数还是静态函数,基类或包含对象的容器都取决于您。

答案 1 :(得分:1)

如果您有一个跨多个类操作的函数,您可以考虑将其作为一个独立的函数。请记住:并非每个函数都需要与类关联(除非您使用的是Java或C#)。因此,你可以有类似的东西:

bool intersects(const T1 &a, const T2 &b);

接下来要考虑的是关系是可能的并且有意义(例如,询问向量是否与矩阵相交是没有意义的)。这将告诉您该方法应该使用哪些类组合。

接下来,考虑方法中的等价性。如果A op B == B op A,那么你可以写:

inline bool intersects(const Vector3 &a, const Plane3 &b)
{
    return intersects(b, a);
}

在实现关系运算符时使用 - 您可以在!===>>=方面实现<= <

这也适用于合成(例如,在intersects对象的xy坐标上调用Point2D

如果您正在编写一个库,您应该首先编写最常见/最有用的组合,并针对一个全面的集合(它们有意义)。如果您正在编写应用程序,则应该专注于提供所需的内容。

答案 2 :(得分:0)

我建议isIntersecting在与ABC相同的名称空间中设置一组非成员函数:

namespace X {
  class A { };
  class B { };
  class C { };
  bool isIntersecting(const A&, const B&);
  bool isIntersecting(const A&, const C&);
  bool isIntersecting(const B&, const C&);
}

如果必须,只会让他们成为朋友。