在C+中多态地应用装饰器模式和耦合问题+; 我尝试制作一个C++实现的棋盘游戏。我正在尝试制作一个瓷砖对象,它有四个侧面和三种基本地形之一(田地、道路、城市)
我能想到的最好的瓷砖创建界面是:在C+中多态地应用装饰器模式和耦合问题+; 我尝试制作一个C++实现的棋盘游戏。我正在尝试制作一个瓷砖对象,它有四个侧面和三种基本地形之一(田地、道路、城市),c++,design-patterns,include,polymorphism,decorator,C++,Design Patterns,Include,Polymorphism,Decorator,我能想到的最好的瓷砖创建界面是: City city; city_city_city_city = new Tile(city, city, city, city); Tile(CityDecorator(new TopSide), CityDecorator(new RightSide), FieldDecorator(new BottomSide), RoadDecorator(new LeftSide)); 其中,平铺类的定义如下所示 class Til
City city;
city_city_city_city = new Tile(city, city, city, city);
Tile(CityDecorator(new TopSide),
CityDecorator(new RightSide),
FieldDecorator(new BottomSide),
RoadDecorator(new LeftSide));
其中,平铺类的定义如下所示
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_;
};
但之前的版本似乎更干净
我的问题是。。。这是一种可接受的方法,还是我缺少一种更简单/更干净的方法
我使用这种方法会遇到耦合问题,因为我必须在Terrain中包含SideDecorator的路径,Terrain在SideDecorator和派生类中使用。terrain.h中的简单指令#include“side_decorator.h”会导致许多编译错误,因此很难判断这是一个正向声明问题还是代码中没有提到的其他问题……让side根据terrain参数而不是viceversa生成修饰结果怎么样?然后,地形将只需要一种方法来指示它所需要的线段,它们的方向可能由侧面来安排。也许这会缓解耦合
与耦合无关,但是考虑在你的设计中更广泛地使用泛型编程——不明显的是,侧面、地形和/或片段不应该使用泛型而不是继承。从某种意义上说,这更多的是一个实现而不是一个设计问题,但它确实会影响设计。不幸的是,我认为我对应用程序领域的理解不够深入,无法提供更具体的建议(我很久以前玩过Carcasonne一次,但除了好玩之外,我不记得太多;-)。
关于循环依赖性问题的注意事项:您可以使用PImpl习惯用法,如本文所述(另一个简单示例) 一块瓷砖有四个面,每一面是田地、道路、城市的一面class Side {
// things common to all sides
};
class Field : public Side {
// things only found in a field
};
class Road : public Side {
// things only found in a road
};
class City : public Side {
// things only in a city
};
class Tile {
collection of 4 Sides;
Tile(Side *top, Side *left, Side *right, Side *bottom);
};
...
// ex. usage:
Tile myTile( new Road, new City, new City, new Field );
为什么这不能满足您的所有需求?
注意:引用、指针等等,这些都是实现细节,对于设计问题来说并不重要。我认为设计模式太过了另一种可能是使用模板
template <class Top, class Right, class Bottom, class Left>
class Tile
{
TopSide top;
RightSide right;
BottomSide bottom;
LeftSide left;
Tile()
{
// imaginary syntax to "decorate" a side
top.type = new Top();
right.type = new Right();
bottom.type = new Bottom();
left.type = new Left();
}
}
Tile<City, Road, City, Field> tile();
模板
类瓷砖
{
上部组块顶部;
右侧右侧;
底部;
左侧左侧;
瓦片()
{
//“装饰”一面的想象语法
top.type=新的top();
right.type=新的right();
bottom.type=新底部();
left.type=新的left();
}
}
瓷砖();
语法将非常清晰,特别是借助于可以自动生成的typedef,例如:
typedef Tile<Field, Road, City, Road> Tile_F_R_C_R;
typedef Tile\u F\R\u C\R;
另一方面,这可能导致生成大量代码。我认为您的解决方案很好。实际上,您需要一个虚拟构造器,根据它所修饰的类型创建正确类型的装饰器。这需要一种工厂方法,即
decoration
is。它隐藏了为平铺创建哪个装饰器的详细信息,但是地形类必须知道它们可以被装饰
如果其他类需要自己的特殊类型的装饰器,我只会对这种设计有问题。然后添加新的类型和装饰将成为一件痛苦的事。但对于一两个定义明确的情况,您的设计是好的
我可以创建具体的类,比如TopFieldSide、BottomRoadway等,但我认为decorator模式会更干净
Decorator模式增加了复杂性,只有当您打算添加新的Decorator,但不想修改主应用程序时,这种复杂性才有回报。如果你的游戏规则是固定的(除了你提到的具体类之外,再也没有别的了),那么我会说这种复杂性是不会有回报的
如果你想应用Decorator来学习或掌握模式,那就去做吧。但请注意,它所解决的问题实际上可能并不存在于您的设计需求中 游戏结束了吗?最近我也开始编写代码(用C++),但时间不多,所以速度很慢。我感兴趣的是,你是否实现了某种AI播放器,或者至少考虑了它的策略?我在研究一种算法时偶然发现了这条线索,该算法可以建议为特定位置保留Carcasonne瓷砖,也就是某种AI播放器@斯佩克特:你找到解决方案了吗?或者也许只是一个可能的解决方案的良好起点?@Jörn还没有。遗憾的是,我的这个项目由于工作等更紧迫的事情而被搁置:(.它的当前状态是:功能编辑器(你可以根据规则放置/旋转瓷砖),可能的瓷砖放置检测(AI的第一步),一些分数计数(未完全实现)。我使用的瓷砖表示为5x5
网格(墙/路径/草)用*检查正确和可能的位置以及分数计算。缺少的是根据AI的实际目标从可能的位置中选择的一些启发式或决策逻辑(上路、城堡、教堂…,阻止玩家…)@Jörn I打算为AI实施一些伪随机决策+最大分数策略,但自2014年4月13日以来,我没有时间/心情这样做或编写任何代码