c++ - C++中装饰器模式的多态应用与耦合问题

标签 c++ design-patterns include polymorphism decorator

我正在尝试制作棋盘游戏的 C++ 实现 Carcassonne .我正在尝试制作一个具有四个面和三个基本地形(田野、道路、城市)之一的瓷砖对象。

我能想到的创建图 block 的最佳界面是以下形式:

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。例如:带有 Field 的 Side 只需要一个 FieldSegment,而带有 Road 的 Side 需要三个 Segment:一个 RoadSegment 和两个 FieldSegment。因此,向板上添加一个图 block 将需要具有不同实现和成员的边。

我可以制作像 TopFieldSide、BottomRoadSide 等具体类,但我认为装饰器模式会更简洁。然而,我不确定的是 Decorate() 方法的多态使用是否是误用。

当然,我可以创建以下形式的 Tiles:

Tile(CityDecorator(new TopSide), 
     CityDecorator(new RightSide),
     FieldDecorator(new BottomSide),
     RoadDecorator(new LeftSide));

但是之前的版本看起来干净多了。

我的问题是......这是一种可接受的方法还是我缺少一种更简单/更清晰的方法?

我对这种方法的使用使我遇到了耦合问题,因为我必须在 Terrain 中包含到 SideDecorator 的路径,而 Terrain 在 SideDecorator 和派生类中使用。 terrain.h 中的简单指令 #include "side_decorator.h"会导致许多编译错误,因此很难判断它是前向声明问题还是我的代码中没有注意到的其他问题...

最佳答案

让 Side 根据 Terrain 参数生成装饰结果怎么样,而不是反之亦然?然后 Terrain 只需要一个方法来指示它需要的 Segments 并且它们的方向可能由 Side 安排。也许这会减轻耦合?

与耦合无关,但请考虑在您的设计中更广泛地使用泛型编程——边、地形和/或线段不应该使用泛型来代替继承或与继承一起使用并不明显。从某种意义上说,这更像是一种实现而不是设计问题,但它确实会影响设计。不幸的是,我认为我对应用程序领域的了解不够深入,无法提供更具体的建议(我确实玩过一次卡尔卡松,很久以前,但除了它很有趣,我不记得太多了;-)。

关于c++ - C++中装饰器模式的多态应用与耦合问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1309725/

相关文章:

c++ - 当我在C++中存储指向按值传递参数的指针时会发生什么?

c++ - 编写一个经常更改的类/结构

c++ - 循环依赖修复

c++ - 如何将类作为参数传递

c++ - 使用 OpenCV 的 ANN 中笨重的 CvMat*

c++ - 如何在数组的一部分中查找特定值的第一个元素

Android:如何实现 "distributed control"

design-patterns - 回调/命令与EventListener/观察者模式

file-io - ansible include_if_exists

c++ - 包含哪个 unistd.h? (c++)