Sono strongmente favorevole alla strategia delineata in la risposta di @DocBrown .
Ho intenzione di suggerire un miglioramento della risposta.
Le chiamate
myMap.Add(1,new Strategy1());
myMap.Add(2,new Strategy2());
myMap.Add(3,new Strategy3());
può essere distribuito. Non è necessario tornare allo stesso file per aggiungere un'altra strategia, che aderisce al principio Open-Closed ancora meglio.
Supponi di implementare Strategy1
nel file Strategy1.cpp. Puoi avere il seguente blocco di codice in esso.
namespace Strategy1_Impl
{
struct Initializer
{
Initializer()
{
getMap().Add(1, new Strategy1());
}
};
}
using namespace Strategy1_Impl;
static Initializer initializer;
Puoi ripetere lo stesso codice in ogni file StategyN.cpp. Come puoi vedere, questo sarà un sacco di codice ripetuto. Per ridurre la duplicazione del codice, puoi utilizzare un modello che può essere inserito in un file accessibile a tutte le classi Strategy
.
namespace StrategyHelper
{
template <int N, typename StrategyType> struct Initializer
{
Initializer()
{
getMap().Add(N, new StrategyType());
}
};
}
Dopodiché, l'unica cosa che devi usare in Strategy1.cpp è:
static StrategyHelper::Initializer<1, Strategy1> initializer;
La riga corrispondente in StrategyN.cpp è:
static StrategyHelper::Initializer<N, StrategyN> initializer;
Puoi usare i modelli su un altro livello usando un modello di classe per le classi di strategia concrete.
class Strategy { ... };
template <int N> class ConcreteStrategy;
E poi, anziché Strategy1
, usa ConcreteStrategy<1>
.
template <> class ConcreteStrategy<1> : public Strategy { ... };
Cambia la classe helper per registrare Strategy
s in:
namespace StrategyHelper
{
template <int N> struct Initializer
{
Initializer()
{
getMap().Add(N, new ConcreteStrategy<N>());
}
};
}
Cambia il codice in Strateg1.cpp in:
static StrategyHelper::Initializer<1> initializer;
Cambia il codice in StrategN.cpp in:
static StrategyHelper::Initializer<N> initializer;