我有以下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]));
}
}
Run Code Online (Sandbox Code Playgroud)
我希望不再需要if ... else(如果可能的话,在下面所述的限制范围内).
我现在的限制是:
我们非常欢迎您提出任何建议/意见/解决方案.
此问题的标准解决方案,特别是考虑到您对依赖关系的限制,是使用访问者模式.
以下是访客模式在您的案例中的工作方式:
ShapeVisitor类.它Visit为Shape的每个具体子类都有一个抽象方法.如: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);
}
}
Run Code Online (Sandbox Code Playgroud)
在这段代码中,我选择CAD实际上是一个子类ShapeVisitor.此外,由于你已经有了虚拟方法CAD来绘制,我实现了Visit那里的方法(一次),而不是在每个子类中实现一次.一旦你将客户端切换到使用AcceptVisitor而不是直接调用Draw*方法,你可以使这些方法受到保护,然后最终将Visit方法的实现向下移动到子类(即:refactor,以消除由此引起的额外级别的间接有Visit(Foo*)通话DrawFoo(Foo*)).
这是DoubleDispatch的经典案例,您需要为每个可能的(Shape,CAD)对使用单独的方法:
isSquare/ isCirclefields.virtual void DrawOn(CAD*)到Shape界面.实施Circle::DrawOn(CAD*)(例如):
void Circle::DrawOn(CAD *c) {
c->DrawCircle(this);
}
Run Code Online (Sandbox Code Playgroud)
这是"技巧",myCircle->DrawOn(mySWX)无论Shape或CAD的类型如何,都可以调用正确的方法调用.
| 归档时间: |
|
| 查看次数: |
981 次 |
| 最近记录: |