Я категорично за стратегію, викладену у відповіді @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;