私は今、異なる形状間の衝突で同じ問題に直面しています。
階層 A (訪問者) のクラスが別の階層 B (訪問された要素) のクラスを訪問する必要があるため、訪問者パターンを「そのまま」使用することはできないと思います。ここで、B のクラスは A の抽象化についてのみ知っています。 ( IVisitorなど) B のクラスは A のサブクラス ( VisitedElement1、VisitedElement2 ... VisitedElement のサブクラス) について知っています。
私たちの場合、Shape クラスをサブクラスから切り離したまま、Shape を持つ Shape を訪問しようとしているので、Visitor パターンは適用されません。
私が考えることができる最善の解決策は、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に違反し、「Shape」と「Figure」の両方でLSPを保持します。
誰かがダウンキャストを回避しながらこれを行うためのより良い方法を提案できる場合、私は非常に感謝しています:D