Avoiding downcasting, double dispatch

Viewed 71

I did something similar to the following code:

void launchPipeline(IQueryFactory & queryFactory, IQuerySender &querySender, IValidateResponse &responseValidator)
{
    std::unique_ptr<IQuery> query = queryFactory.getInstance();

    /*
    auto a,b,c = querySender.send(query);
    //we just get a lot of params from that function
    */

    if(responseValidator.validate(query, a, b, c)
    {
        //do something
    }
}
class IValidateResponse
{
   public:
    virtual bool validate(IQuery & query, int a, int b, int c) = 0;
};

class QueryAValidator
{
   public:
    bool validate(IQuery & query, int a, int b, int c) override
    {
        const auto & queryA = dynamic_cast<const QueryA &>(query);
        //do something
    }
};

It works perfectly fine because matching types of IQueryFactory and IValidateResponse are injected in. But I was wondering if this could be avoided in some fancy way?

I was thinking about QueryVisitor but I'm not sure how to implement it, the visit function would require to take a, b, c params which would look weird on IQuery interface, like query.accept(visitor, a, b, c).

Or I could store these params inside the visitor, but that still doesn't feel smooth, especially when it comes to writing tests. For now I have so called "validators tests" where I simply put fake response and test the concrete Validator class, adding visitor to that would make them more complicated.

How would you solve that?

1 Answers

Define a pure virtual function in IQuery and call it foo(int a, int b, int c). In QueryA you override foo with the code you defined with "//do something" after the dynamic cast. Replace the dynamic cast with query.foo(a, b, c)

Related