Sto cercando di capire il reale requisito dell'utilizzo di modelli per la progettazione basata su criteri. Passando attraverso i nuovi modelli basati su modelli in C++ ho scoperto che il design di classi basato su policy è un modo di progettazione altamente consigliato che consente di "plug-in" comportamenti diversi da classi di policy. Un esempio minimo è la seguente (una versione ridotta del wiki):Quando preferire la struttura basata su criteri basata su modelli basati su ereditarietà non basata su modelli
template <typename LanguagePolicy>
class HelloWorld : private LanguagePolicy
{
using LanguagePolicy::message;
public:
// Behaviour method
void run() const
{
// policy methods
cout << message();
}
};
class LanguagePolicyA
{
protected:
std::string message() const
{
return "Hello, World!";
}
};
//usage
HelloWorld<LanguagePolicyA> hello_worlda;
hello_worlda.run(); // prints "Hello, World!"
Una rapida analisi mostra che solo per ottenere diversi metodi plugable message()
vengono ereditati da un tipo template cui definizione può essere fornita da chiunque (e identificato al momento della compilazione).
Tuttavia, lo stesso livello di astrazione (e metodi configurabili) può essere ottenuto senza l'utilizzo di un codice basato su modelli e del semplice polimorfismo di run time della vecchia scuola, come illustrato di seguito.
class HelloWorld
{
LanguagePolicy *lp; //list of all plugable class
public:
HelloWorld(LanguagePolicy *lpn) {
lp = lpn;
}
// Behaviour method
void run() const
{
// policy methods
cout << lp->message();
}
};
class LanguagePolicy
{
protected:
virtual std::string message() const;
};
class LanguagePolicyA: LanguagePolicy
{
protected:
std::string message() const
{
return "Hello, World!";
}
};
//usage
HelloWorld helloworld(new LanguagePolicyA);
helloworld.run();
funzionalità ed il livello di astrazione saggio non vedo molta differenza nelle due approccio (anche se il secondo approccio ha poche righe in più di codice per LanguagePolicy
, penso che è necessario per gli altri utenti per conoscere l'interfaccia, altrimenti la comprensione di LanguagePolicy
dipende dalla documentazione). Ma penso che più tardi sia "pulito" (proveniente da qualcuno che non ha usato molto il modello). Questo perché personalmente secondo me le classi non basate su modelli sono più pulite da guardare e capire. Un esempio estremamente valido è la famosa libreria VTK (Visualization Tool Kit) che risolve molti problemi diversi utilizzando il secondo approccio. Anche se non ci sono ampie documentazioni su VTK, molti di noi - i suoi utenti, possono solo dare un'occhiata ai suoi diagrammi di classe (a volte sono piuttosto grandi) e dedurre comportamenti di classi; e sviluppare pipeline altamente configurabili e complicate nella nostra applicazione (non è possibile eseguire l'imaging di VTK come modello :)). L'opposto è librerie come STL/BOOST che non credo sia possibile per chiunque sia in grado di identificare il funzionamento delle classi senza l'uso di un'ampia documentazione.
Quindi la mia domanda è, il modello di progettazione basato su modelli è davvero superiore (solo in questo scenario di progettazione basata su criteri) rispetto all'ereditarietà virtuale basata? Se è così, quando e perché?
-> Il modello 'simula' il polimorfismo del tempo di esecuzione generando le classi in fase di compilazione. Quindi, perché non utilizzare direttamente il runtime? Perché ci importa? -> Darò un'occhiata, ma quanto costa veramente il sovraccarico sulle chiamate virtuali? Sono abbastanza significativi da causare un effetto? – krips89
@ krips89 Il secondo punto. Esiste un sovraccarico delle prestazioni con le chiamate virtuali, che può essere importante in alcuni casi. –
@ krips89 Dipende, ma se si prende in considerazione l'indirezione, il pasticcio con le linee della cache, la possibilità che una funzione basata su modelli sia in linea, ci può essere un vantaggio dall'uso delle politiche. –