Я пытаюсь сделать реализацию настольной игры на C ++ Carcassonne . Я пытаюсь сделать объект из плиток, который имеет четыре стороны и одну из трех основных ландшафтов (поле, дорога, город).
Лучший интерфейс для создания плитки, который я мог придумать, имел вид:
City city;
city_city_city_city = new Tile(city, city, city, city);
Где класс Tile определяется следующим образом ...
class Tile
{
public:
Tile(Terrain& top_terrain,
Terrain& right_terrain,
Terrain& bottom_terrain,
Terrain& left_terrain)
{
top_side_.reset(top_terrain.Decorate(new TopSide()));
right_side_.reset(right_terrain.Decorate(new RightSide());
bottom_side_.reset(bottom_terrain.Decorate(new BottomSide()));
left_side_.reset(left_terrain.Decorate(new LeftSide()));
}
private:
boost::scoped_ptr<TopSide> top_side_;
boost::scoped_ptr<RightSide> right_side_;
boost::scoped_ptr<BottomSide> bottom_side_;
boost::scoped_ptr<LeftSide> left_side_;
};
Я хотел, чтобы конструктор инициализировал каждую конкретную сторону (TopSide, RightSide, BottomSide, LeftSide), которая наследуется от базового класса Side. Идея заключалась в том, чтобы определить виртуальный метод Decorate в классе Terrain, который бы возвращал экземпляр SideDecorator для определенного типа Terrain.
В зависимости от типа ландшафта, который имеет сторона, она будет иметь различное количество / тип сегментов Terrain. Например: Сторона с полем нуждается только в одном FieldSegment, тогда как Сторона с дорогой нуждается в трех Сегментах: RoadSegment и два FieldSegment. Таким образом, для добавления плитки на доску потребуются Стороны с различными реализациями и участниками.
Я мог бы создавать конкретные классы, такие как TopFieldSide, BottomRoadSide и т. Д., Но я подумал, что шаблон декоратора будет чище. Однако я не уверен в том, является ли полиморфное использование метода Decorate () неправомерным.
Конечно, я мог бы создать плитки вида:
Tile(CityDecorator(new TopSide),
CityDecorator(new RightSide),
FieldDecorator(new BottomSide),
RoadDecorator(new LeftSide));
Но предыдущая версия кажется намного чище.
Мой вопрос в том, что ... Это приемлемый подход или есть более простой / чистый способ, которого мне не хватает?
Мое использование этого подхода заставляет меня сталкиваться с проблемами связывания, потому что я должен включить путь к SideDecorator в Terrain, а Terrain используется в SideDecorator и в производных классах. Простая директива #include "side_decorator.h" в terrain.h вызывает много ошибок компиляции, из-за чего трудно определить, является ли это проблемой предварительного объявления или что-то еще не скомпрометировано в моем коде ...