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.