Sou totalmente a favor da estratégia descrita na resposta do @DocBrown .
Vou sugerir uma melhoria para a resposta.
As chamadas
myMap.Add(1,new Strategy1());
myMap.Add(2,new Strategy2());
myMap.Add(3,new Strategy3());
pode ser distribuído. Você não precisa voltar ao mesmo arquivo para adicionar outra estratégia, que adere ao princípio Aberto-Fechado ainda melhor.
Digamos que você implemente Strategy1
no arquivo Strategy1.cpp. Você pode ter o seguinte bloco de código nele.
namespace Strategy1_Impl
{
struct Initializer
{
Initializer()
{
getMap().Add(1, new Strategy1());
}
};
}
using namespace Strategy1_Impl;
static Initializer initializer;
Você pode repetir o mesmo código em todos os arquivos StategyN.cpp. Como você pode ver, haverá muito código repetido. Para reduzir a duplicação de código, você pode usar um modelo que pode ser colocado em um arquivo acessível a todas as Strategy
classes.
namespace StrategyHelper
{
template <int N, typename StrategyType> struct Initializer
{
Initializer()
{
getMap().Add(N, new StrategyType());
}
};
}
Depois disso, a única coisa que você deve usar no Strategy1.cpp é:
static StrategyHelper::Initializer<1, Strategy1> initializer;
A linha correspondente no StrategyN.cpp é:
static StrategyHelper::Initializer<N, StrategyN> initializer;
Você pode levar o uso de modelos para outro nível usando um modelo de classe para as classes concretas da Strategy.
class Strategy { ... };
template <int N> class ConcreteStrategy;
E então, em vez de Strategy1
, use ConcreteStrategy<1>
.
template <> class ConcreteStrategy<1> : public Strategy { ... };
Altere a classe auxiliar para registrar Strategy
s para:
namespace StrategyHelper
{
template <int N> struct Initializer
{
Initializer()
{
getMap().Add(N, new ConcreteStrategy<N>());
}
};
}
Altere o código em Strateg1.cpp para:
static StrategyHelper::Initializer<1> initializer;
Altere o código no StrategN.cpp para:
static StrategyHelper::Initializer<N> initializer;