我现在面临着不同形状之间碰撞的同样问题。
我认为我们不能“按原样”使用访问者模式,因为它要求层次 A(访问者)的类访问另一个层次 B(访问的元素)的类,其中 B 的类只知道 A 的抽象(例如IVisitor)而 B 的类知道 A 的子类(VisitedElement1,VisitedElement2 ... VisitedElement 的子类)。
在我们的例子中,我们尝试使用 Shapes 访问 Shapes,同时保持 Shape 类与子类分离,因此访问者模式不适用。
我能想到的最佳解决方案是 Shape 类直接或通过另一个接口为所有子类型声明“GetSpecificIntersection”方法:
class Shape
{
.....
public:
virtual bool GetIntersection(Shape* _shape) = 0;
protected:
virtual bool GetSpecificIntersection(Circle* _circle) = 0;
virtual bool GetSpecificIntersection(Triangle* _triangle) = 0;
}
class Circle
{
.....
public:
virtual bool GetIntersection(Shape* _shape);
{
return _shape->GetSpecificIntersection(this);
}
protected:
virtual bool GetSpecificIntersection(Circle* _circle) { ... }
virtual bool GetSpecificIntersection(Triangle* _triangle) { ... }
}
class Triangle { /* analog to Circle */ }
因此,您必须为每种形状与任何其他类型的形状实现这些特定的交集方法,并且 Shape 类与所有可能的形状耦合。如果我没记错的话,这违反了OCP但保留了LSP。
我刚刚提出的另一个选择是“优先组合而不是继承”并制作如下内容:
class Shape
{
.....
public:
virtual bool GetIntersection(Shape* _shape)
{
return _shape->figure->GetIntersection(this->figure);
}
private:
Figure* figure;
}
class Figure
{
.....
public:
virtual bool GetIntersection(Figure* _figure) = 0;
protected:
virtual bool GetSpecificIntersection(Circle* _circle) = 0;
virtual bool GetSpecificIntersection(Triangle* _triangle) = 0;
}
class Circle
{
.....
public:
virtual bool GetIntersection(Figure* _figure)
{
return _figure->GetSpecificIntersection(this);
}
protected:
virtual bool GetSpecificIntersection(Circle* _circle) { ... }
virtual bool GetSpecificIntersection(Triangle* _triangle) { ... }
}
class Triangle { /* analog to Circle */ }
它和以前一样,但是通过这样做,你将你的 Shape 类(这是你的游戏类使用的接口)与不同的“Figures”(我没有想出更好的名字)解耦,所以添加新的图形甚至不应该导致重新编译您的客户端类。这仅在“图形”层次结构中违反OCP ,并为“形状”和“图形”保留LSP 。
如果有人可以提出更好的方法来避免沮丧,我将非常感激:D