Я решительно поддерживаю стратегию, изложенную в ответе @DocBrown .
Я собираюсь предложить улучшение ответа.
Звонки
myMap.Add(1,new Strategy1());
myMap.Add(2,new Strategy2());
myMap.Add(3,new Strategy3());
можно распространять. Вам не нужно возвращаться к тому же файлу, чтобы добавить другую стратегию, которая еще лучше придерживается принципа Open-Closed.
Скажем, вы реализуете Strategy1
в файле Strategy1.cpp. Вы можете иметь следующий блок кода в нем.
namespace Strategy1_Impl
{
struct Initializer
{
Initializer()
{
getMap().Add(1, new Strategy1());
}
};
}
using namespace Strategy1_Impl;
static Initializer initializer;
Вы можете повторить один и тот же код в каждом файле StategyN.cpp. Как видите, это будет много повторяющегося кода. Чтобы уменьшить дублирование кода, вы можете использовать шаблон, который можно поместить в файл, доступный для всех Strategy
классов.
namespace StrategyHelper
{
template <int N, typename StrategyType> struct Initializer
{
Initializer()
{
getMap().Add(N, new StrategyType());
}
};
}
После этого единственное, что вам нужно использовать в Strategy1.cpp:
static StrategyHelper::Initializer<1, Strategy1> initializer;
Соответствующая строка в StrategyN.cpp:
static StrategyHelper::Initializer<N, StrategyN> initializer;
Вы можете перенести использование шаблонов на другой уровень, используя шаблон класса для конкретных классов Стратегии.
class Strategy { ... };
template <int N> class ConcreteStrategy;
А потом вместо Strategy1
использования ConcreteStrategy<1>
.
template <> class ConcreteStrategy<1> : public Strategy { ... };
Измените вспомогательный класс для регистрации Strategy
s:
namespace StrategyHelper
{
template <int N> struct Initializer
{
Initializer()
{
getMap().Add(N, new ConcreteStrategy<N>());
}
};
}
Измените код в Strateg1.cpp на:
static StrategyHelper::Initializer<1> initializer;
Измените код в StrategN.cpp на:
static StrategyHelper::Initializer<N> initializer;