Я сейчас сталкиваюсь с той же проблемой с столкновениями между разными формами.
Я думаю, что мы не можем использовать шаблон Посетитель «как есть», потому что он требует, чтобы классы иерархии A (посетители) посещали классы другой иерархии B (посещаемые элементы), где классы B знают только об абстракции A (например, IVisitor), в то время как классы B знают о подклассах A (VisitedElement1, VisitedElement2... подклассы VisitedElement).
В нашем случае мы пытаемся посетить фигуры с помощью фигур, сохраняя при этом наш класс фигуры отделенным от подклассов, поэтому шаблон посетителя не применяется.
Лучшее решение, которое я могу придумать, это то, что класс 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 (который является интерфейсом, используемым классами вашей игры) от разных «фигур» (я не придумал лучшего имени), поэтому добавляя новый Цифры не должны даже приводить к перекомпиляции ваших клиентских классов. Это нарушает OCP только в иерархии "Рисунки" и сохраняет LSP как для "Формы", так и для "Фигура".
Если кто-то может предложить лучший способ сделать это, избегая понижения, я буду очень благодарен: D
person
sergiou87
schedule
18.09.2012