3

I am writing a rather large class where the user can specify at runtime whether she wants to use algorithm A or B of an third party library e. Basically there is only one function call different in choosing A or B, but this function is called in many different places in the code.

I would like to omit having to write

if (user_chose_A) {
  call_A_algo();
} else {
  call_B_algo();
}

all over my code and I am wondering what's a nice solution for my problem (in C++11).

I was thinking about storing two function pointers (std::function), one to algorithm A and one to B and then have one function in my class which returns the correct function pointer.

Since my scenario seems like a rather common situation, I am wondering what's best practice here.

  • 5
    Pass the function as a parameter to your other methods (i.e. use a higher-order function.) – Robert Harvey May 9 '16 at 22:22
5

The common object-oriented approach for hiding implementation details (in this case A_algo and B_algo are implementation details) is to find a connection between the two (or among three or more) functions and to define a new generic interface (in C++ a pure abstract class), which is then instantiated by some sort of a factory.

In object-oriented terms, this is mostly refered to as the adapter design pattern, when you provide same interface for two seemingly different things.

class AlgorithmAdapter
{
public:
    virtual void run() const = 0;
};

class AlgorithmOneAdapter : public AlgorithmAdapter
{
public:
    void run() const
    {
        call_A_algo();
    }
};

class AlgorithmTwoAdapter : public AlgorithmAdapter
{
public:
    void run() const
    {
        call_B_algo();
    }
};

// some function
void runsAlgorithm(AlgorithmAdapter const & algorithm)
{
    algorithm.run(); // <- does not care whether it's algo_A or algo_B,
                     // but it knows, the run method is available
}

You would then have the factory, which would contain a switch statement, providing a concrete implementation of AlgorithmAdapter interface, on which you'd know the run method is available.


Why is this good?

You delegate the algorithm decision from your business logic layer to a factory class, which is only responsible for object graph creation (see separation of concerns).

Is it worth it?

Creating 3 or more classes just so you can abstract the call? Maybe even not, depends on your requirements.

Is there an easier way?

I mentioned a factory, which is pretty much just a simple switch/case function/method. You can do the same without having to define the 3 new adapter classes, by defining a new function/metod, putting the decision in there based on a parameter value that is being passed and using this method throughout your code (working with functions directly is more procedural approach than object-oriented one).

It is much faster to get done, but kind of mixes responsibilities (with that approach you'd have a function which would do both, make the decision which algorithm should be chosen and run it).

You could also pass a function pointer as a parameter to a function, thus in a function you'd be specific algorithm ignorant, but even then, you'd still have to make the decision which algorithm to choose somewhere. No matter how hard you'll try, there will always be place in a code which will know how to wire components together based on some rules, it's inevitable.

  • I like your adapter pattern approach, I thinks this is cleaner than my function pointer "hack". – user695652 May 9 '16 at 22:40
  • What if we alter the scenario so that Algorithm A and Algorithm B each take one parameter, but of different type (no common superclass). Is there anything we can do (in the AlgorithmAdapter class) to have a generic adapter? – user695652 May 10 '16 at 13:56
  • @user695652 I guess it depends. If you could pull the parameters which is different from configuration, then you could just have it stored inside the factory object providing the factory method. But if the value was specific to one call, you would probably need to create some sort of a messenger object, basically a value type, with optional attributes, pass this value object to the factory method which would know, based on the algorithm type that was chosen, which attribute it should pull out of the object you pass along with the algorithm-run request. – Andy May 10 '16 at 16:53
1

The Factory Pattern is used to handle similar situations, but in the context of OOP. You would essentially have a standalone class for each algorithm, an interface they implement so they can be used interchangeably, and a method that uses arguments (the user's input, in this case) to decide which class to instantiate. Your function pointer solution is essentially the same concept, minus the OOP.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.