Je suis fortement en faveur de la stratégie décrite dans la réponse de @DocBrown .
Je vais suggérer une amélioration de la réponse.
Les appels
myMap.Add(1,new Strategy1());
myMap.Add(2,new Strategy2());
myMap.Add(3,new Strategy3());
peut être distribué. Vous n'avez pas besoin de revenir au même fichier pour ajouter une autre stratégie, qui adhère encore mieux au principe Open-Closed.
Supposons que vous implémentiez le Strategy1
fichier Strategy1.cpp. Vous pouvez contenir le bloc de code suivant.
namespace Strategy1_Impl
{
struct Initializer
{
Initializer()
{
getMap().Add(1, new Strategy1());
}
};
}
using namespace Strategy1_Impl;
static Initializer initializer;
Vous pouvez répéter le même code dans chaque fichier StategyN.cpp. Comme vous pouvez le voir, ce sera beaucoup de code répété. Pour réduire la duplication de code, vous pouvez utiliser un modèle qui peut être placé dans un fichier accessible à toutes les Strategy
classes.
namespace StrategyHelper
{
template <int N, typename StrategyType> struct Initializer
{
Initializer()
{
getMap().Add(N, new StrategyType());
}
};
}
Après cela, la seule chose que vous devez utiliser dans Strategy1.cpp est:
static StrategyHelper::Initializer<1, Strategy1> initializer;
La ligne correspondante dans StrategyN.cpp est:
static StrategyHelper::Initializer<N, StrategyN> initializer;
Vous pouvez amener l'utilisation des modèles à un autre niveau en utilisant un modèle de classe pour les classes de stratégie concrètes.
class Strategy { ... };
template <int N> class ConcreteStrategy;
Et puis, au lieu de Strategy1
, utilisez ConcreteStrategy<1>
.
template <> class ConcreteStrategy<1> : public Strategy { ... };
Modifiez la classe d'assistance pour enregistrer Strategy
s en:
namespace StrategyHelper
{
template <int N> struct Initializer
{
Initializer()
{
getMap().Add(N, new ConcreteStrategy<N>());
}
};
}
Modifiez le code dans Strateg1.cpp en:
static StrategyHelper::Initializer<1> initializer;
Changez le code dans StrategN.cpp en:
static StrategyHelper::Initializer<N> initializer;