L'approccio comune orientato agli oggetti per nascondere i dettagli di implementazione (in questo caso A_algo
e B_algo
sono dettagli di implementazione) è trovare una connessione tra le due (o tra tre o più) funzioni e definire un nuovo generico interfaccia (in C ++ una pura classe astratta), che viene quindi istanziata da una sorta di fabbrica .
In termini orientati agli oggetti, questo è per lo più indicato come modello di progettazione dell'adattatore, quando fornisci la stessa interfaccia per due cose apparentemente diverse.
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
}
Avresti quindi la factory, che conterrebbe un'istruzione switch
, fornendo un'implementazione concreta dell'interfaccia AlgorithmAdapter
, sulla quale sapresti che il metodo run
è disponibile.
Perché è buono?
Delega la decisione dell'algoritmo dal tuo livello di business logic a una classe factory, che è responsabile solo della creazione del grafo di oggetti (vedi separazione di preoccupazioni ).
Ne vale la pena?
Creazione di 3 o più classi solo per poter astrarre la chiamata? Forse anche no, dipende dalle tue esigenze.
C'è un modo più semplice?
Ho menzionato una fabbrica, che è praticamente una semplice funzione% / metodo switch/case
. Puoi fare lo stesso senza dover definire le 3 nuove classi di adattatori, definendo una nuova funzione / metodo, inserendo la decisione in base al valore del parametro che viene passato e usando questo metodo per tutto il codice (lavorare direttamente con le funzioni è approccio più procedurale rispetto a quello orientato agli oggetti)
È molto più veloce da fare, ma un po 'mixa le responsabilità (con questo approccio avresti una funzione che farebbe entrambe le cose, prendere la decisione su quale algoritmo dovrebbe essere scelto ed eseguirlo).
Potresti anche passare un puntatore a funzione come parametro a una funzione, quindi in una funzione ignorerai l'algoritmo specifico, ma anche in questo caso, dovresti comunque decidere quale algoritmo scegliere da qualche parte . Non importa quanto duramente proverai, ci sarà sempre posto in un codice che saprà come collegare i componenti insieme in base ad alcune regole, è inevitabile.