C ++ How to replace this if ... else statement?

I have the following C ++ code (simplified version):

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]));
    }
}

I want to remove the need for if ... else (if possible within the limits indicated below).

My limitations right now:

  • CAD and derived classes are ginormous classes with various external dependencies.
  • CAD courses cannot be combined with Shape and derived classes (this would be ideal, since then I can use polymorphism to solve my problem), since other projects / classes depend on Shape classes and cannot depend on CAD classes.
  • , , , , ... else - , - ( , ).

//, , .

+3
9

, , .

, :

  • ShapeVisitor. Visit . : Visit(Circle*), Visit(Square*) ..
  • AcceptVisitor(ShapeVisitor*).
  • Shape AcceptVisitor visitor->Visit(this)
  • CAD ( -a, ) a ShapeVisitor. Visit Shape. .

, Visitor :

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 Draw *, , Visit ( : , , Visit(Foo*) DrawFoo(Foo*)).

+8

DoubleDispatch, (Shape, CAD)

  • Nuke isSquare/isCircle.
  • virtual void DrawOn(CAD*) Shape.
  • Circle::DrawOn(CAD*) ():

    void Circle::DrawOn(CAD *c) {
      c->DrawCircle(this);
    }
    

    "", myCircle->DrawOn(mySWX), .

+6

OO, DrawXxxx Draw(). , Draw(), Draw Shape. Draw Shape, .

isXxxx . , , instanceof ( , , ).

+1

SWX- > Draw ( [i]);? Draw , , , ?

+1

. - . , cad.

class Shape
{
    virtual void DrawWithCAD(CAD * cad) = 0;
}

class Circle : public Shape
{
    virtual void DrawWithCAD(CAD * cad)
    {
        cad->DrawCircle(this);
    }
}

class Square : public Shape
{
    virtual void DrawWithCAD(CAD * cad)
    {
        cad->DrawSquare(this);
    }
}

main() :

for( int i = 0 ; i < shapes.size() ; ++i )
{
    shapes[i]->DrawWithCAD(swx);
}
+1

ICAD? CAD , :

class Shape
{
    Draw(ICAD* cad) = 0;        
}

class Circle : public Shape
{
    Draw(ICAD* cad)
    {
        ICAD->DrawCircle(self)
     }
}

class Square : public Shape
{
    Draw(ICAD* cad)
    {
        ICAD->DrawSquare(self)
     }
}

DrawSquare (self) , , .

class ICAD
{
    virtual DrawSquare(Square* square) = 0;
    virtual DrawCircle(Circle * circle) = 0;
}

, CAD , , Shape.

class CAD : public ICAD
{
    // big CAD class...
}

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]->Draw(swx);
    }
}
+1

, CAD:: Draw . - :

class CAD {
  public:
    virtual void Draw(const Circle& circle) = 0;
    virtual void Draw(const Square& square) = 0;
};

Draw - if.

0

, , - - "" (, , , , ).

SWX Shape Draw, :

class Shape
{
public:
    virtual void DrawOnto(Canvas& canvas) = 0;
};

class Circle : public Shape
{
public:
    virtual void DrawOnto(Canvas& canvas);
};

void Circle::DrawOnto(Canvas& canvas)
{
    // ..., e.g.:
    canvas.DrawEllipse(center.x, center.y, radius, radius);
}

...

class SWX : public CAD
{
private:
    Canvas canvas;
public:
    void Draw(Shape& shape)
    {
        shape.DrawOnto(this.canvas);
        // ^ this is the place where your if..else used to be
    }
};
0

Write a few global Draw functions overloaded for each form ... (DrawCircle and friends are virtual, so we can use polymorphism to call CAD objects)

void Draw(CAD *cad, Circle *circle){
    cad->DrawCircle(circle);
}

void Draw(CAD *cad, Square *square){
    cad->DrawSquare(square);
}
0
source

Source: https://habr.com/ru/post/1730331/


All Articles