Sono fortemente a favore della strategia delineata nella risposta di @DocBrown .
Sto per suggerire un miglioramento alla 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 ancora meglio al principio Open-Closed.
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, sarà un sacco di codice ripetuto. Per ridurre la duplicazione del codice, è possibile utilizzare un modello che può essere inserito in un file accessibile a tutte le Strategy
classi.
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;
È possibile portare l'uso dei modelli a un altro livello utilizzando un modello di classe per le classi di strategia concrete.
class Strategy { ... };
template <int N> class ConcreteStrategy;
E poi, invece di Strategy1
, utilizzare 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>());
}
};
}
Modificare il codice in Strateg1.cpp in:
static StrategyHelper::Initializer<1> initializer;
Modificare il codice in StrategN.cpp in:
static StrategyHelper::Initializer<N> initializer;