我正在尝试制作棋盘游戏 Carcassonne 的 C++ 实现。我正在尝试制作一个具有四个边和三个基本地形(田野、道路、城市)之一的瓷砖对象。
我能想到的创建磁贴的最佳界面是以下形式:
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_;
};
我希望构造函数初始化从基类 Side 继承的每个特定 Side(TopSide、RightSide、BottomSide、LeftSide)。这个想法是在 Terrain 类中定义一个虚拟的 Decorate 方法,该方法将为特定类型的 Terrain 返回一个 SideDecorator 的实例。
根据一侧的地形类型,它将具有不同数量/类型的 TerrainSegments。例如:带有字段的一侧只需要一个 FieldSegment,而带有道路的一侧需要三个 Segment:一个 RoadSegment 和两个 FieldSegment。因此,将磁贴添加到板上将需要具有不同实现和成员的 Sides。
我可以创建像 TopFieldSide、BottomRoadSide 等的具体类,但我认为装饰器模式会更简洁。然而,我不确定的是 Decorate() 方法的多态使用是否是误用。
当然,我可以创建以下形式的瓷砖:
Tile(CityDecorator(new TopSide),
CityDecorator(new RightSide),
FieldDecorator(new BottomSide),
RoadDecorator(new LeftSide));
但是以前的版本似乎要干净得多。
我的问题是......这是一种可以接受的方法还是我缺少的更简单/更清洁的方法?
我对这种方法的使用使我遇到了耦合问题,因为我必须在 Terrain 中包含 SideDecorator 的路径,并且在 SideDecorator 和派生类中使用了 Terrain。 Terrain.h 中的简单指令 #include "side_decorator.h"会导致许多编译错误,因此很难判断它是前向声明问题还是我的代码中没有注意到的其他内容...
最佳答案
让 Side 产生基于 Terrain 参数的装饰结果,而不是反之亦然呢?那么 Terrain 只需要一个方法来指示它需要的 Segment,它们的方向可能由 Side 安排。也许这会缓解耦合?
与耦合无关,但考虑在您的设计中更广泛地使用泛型编程——侧面、地形和/或段不应该使用泛型而不是继承,这并不明显。从某种意义上说,这更像是一种实现而不是设计问题,但它确实会影响设计。不幸的是,我认为我对应用程序领域的理解不够深入,无法提供更具体的建议(我确实玩过一次 Carcassonne,很久以前,但除了它很有趣之外,我不记得太多了;-)。
关于c++ - 多态应用装饰器模式和C++中的耦合问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1309725/