我有以下C++代码(简化版本):
class Shape
{
bool isCircle = false;
bool isSquare = false;
}
class Circle : public Shape
{
// some special members/methods
}
class Square : public Shape
{
// some special members/methods
}
class CAD
{
virtual DrawCircle(Circle * circle) = 0;
}
class SWX : public CAD
{
virtual DrawCircle(Circle * circle){// do some stuff that draws circle on SWX system}
}
class PRO : public CAD
{
virtual DrawCircle(Circle * circle){// do some stuff that draws circle on PRO system}
}
int main()
{
Circle * circle = new Circle();
circle->isCircle = true;
Square * sq = new Square;
sq->isSquare = true;
vector<Shape*> shapes;
shapes.push_back(circle);
shapes.push_back(sq);
SWX * swx = new SWX();
for( int i = 0 ; i < shapes.size() ; ++i )
{
if( shapes[i]->isCircle )
{
SWX->DrawCircle((Circle*)(shapes[i]));
}
else if( shapes[i]->isSquare )
{
SWX->DrawSquare((Square*)(shapes[i]));
}
}我希望消除对if...else的需求(如果有可能的话,在下面所述的约束范围内)。
我现在的限制是:
欢迎您提出任何建议/意见/解决方案。
发布于 2010-01-28 06:18:52
这个问题的标准解决方案,特别是考虑到有关依赖关系的约束,是使用访客模式。
下面是访问者模式在您的情况下的工作方式:
ShapeVisitor类。对于每个具体的形状子类,它都有一个抽象的Visit方法。例如:Visit(Circle*),Visit(Square*)等。AcceptVisitor(ShapeVisitor*)方法。AcceptVisitor实现为调用visitor->Visit(this)CAD类都是一个(或有-a,由您决定)一个ShapeVisitor。Visit方法为特定类型的Shape执行适当的绘图。不需要有条件或铸造。下面是您的代码的修改版本,它以一种非常低影响的方式使用访问者模式:
class Circle;
class Square;
class ShapeVisitor
{
virtual void Visit(Circle *circle) = 0;
virtual void Visit(Square *square) = 0;
}
class Shape
{
virtual void AcceptVisitor(ShapeVisitor *visitor) = 0;
}
class Circle : public Shape
{
// some special members/methods
virtual void AcceptVisitor(ShapeVisitor *visitor)
{
visitor->Visit(this);
}
}
class Square : public Shape
{
// some special members/methods
virtual void AcceptVisitor(ShapeVisitor *visitor)
{
visitor->Visit(this);
}
}
class CAD : public ShapeVisitor
{
virtual DrawCircle(Circle *circle) = 0;
virtual DrawSquare(Square *square) = 0;
virtual void Visit(Circle *circle) {
DrawCircle(circle);
}
virtual void Visit(Square *square) {
DrawSquare(square);
}
}
class SWX : public CAD
{
virtual DrawCircle(Circle *circle){// do some stuff that draws circle on SWX system}
}
class PRO : public CAD
{
virtual DrawCircle(Circle * circle){// do some stuff that draws circle on PRO system}
}
int main()
{
Circle * circle = new Circle();
Square * sq = new Square;
vector<Shape*> shapes;
shapes.push_back(circle);
shapes.push_back(sq);
SWX * swx = new SWX();
for( int i = 0 ; i < shapes.size() ; ++i )
{
shapes[i]->AcceptVisitor(SWX);
}
}在这段代码中,我选择了让CAD实际上成为ShapeVisitor的子类。另外,由于您已经在CAD中获得了用于绘图的虚拟方法,所以我在那里实现了Visit方法(一次),而不是在每个子类中实现一次。一旦您将客户端切换到使用AcceptVisitor而不是直接调用Visit(Foo*) *方法,您就可以使这些方法受到保护,然后最终将Visit方法的实现转移到子类中(即:重构以删除Visit(Foo*)调用DrawFoo(Foo*)所导致的额外间接)。
发布于 2010-01-28 06:19:44
这是DoubleDispatch的一个典型案例,您需要为每个可能的(Shape,CAD)对有一个单独的方法:
isSquare/isCircle字段进行核武器化。virtual void DrawOn(CAD*)添加到Shape接口。Circle::DrawOn(CAD*) (例如):
空圆::DrawOn(CAD *c) {c->Draw循环(此);}
这是一个“技巧”,它允许像myCircle->DrawOn(mySWX)这样的调用调用正确的方法,而不管形状的类型或CAD。发布于 2010-01-28 06:19:15
您已经有了一些非常不稳定的OO,但是至少DrawXxxx应该成为going ()。然后,圆形、正方形和其他形状将定义一个Draw()方法,该方法为形状上的虚拟绘图方法提供一个实现。然后你只需调用任何形状的绘图,它就会做正确的事情。
isXxxx的布尔人也应该去。类知道它们是什么以及它们的实例可以告诉您(尽管不需要检查何时绘制,因为这将是一个虚拟方法调用)。
https://stackoverflow.com/questions/2152636
复制相似问题