Jestem zdecydowanie za strategią przedstawioną w odpowiedzi @DocBrown .
Mam zamiar zasugerować poprawę odpowiedzi.
Połączenia
myMap.Add(1,new Strategy1());
myMap.Add(2,new Strategy2());
myMap.Add(3,new Strategy3());
może być dystrybuowany. Nie musisz wracać do tego samego pliku, aby dodać kolejną strategię, która jeszcze lepiej przestrzega zasady Open-Closed.
Załóżmy, że implementujesz Strategy1
w pliku Strategy1.cpp. Możesz mieć następujący blok kodu.
namespace Strategy1_Impl
{
struct Initializer
{
Initializer()
{
getMap().Add(1, new Strategy1());
}
};
}
using namespace Strategy1_Impl;
static Initializer initializer;
Możesz powtórzyć ten sam kod w każdym pliku StategyN.cpp. Jak widać, będzie to dużo powtarzającego się kodu. Aby zmniejszyć duplikację kodu, możesz użyć szablonu, który można umieścić w pliku dostępnym dla wszystkich Strategy
klas.
namespace StrategyHelper
{
template <int N, typename StrategyType> struct Initializer
{
Initializer()
{
getMap().Add(N, new StrategyType());
}
};
}
Następnie jedyną rzeczą, której musisz użyć w Strategy1.cpp, jest:
static StrategyHelper::Initializer<1, Strategy1> initializer;
Odpowiednia linia w StrategyN.cpp to:
static StrategyHelper::Initializer<N, StrategyN> initializer;
Możesz przenieść szablony na inny poziom, używając szablonu klas dla konkretnych klas strategii.
class Strategy { ... };
template <int N> class ConcreteStrategy;
I zamiast tego Strategy1
użyj ConcreteStrategy<1>
.
template <> class ConcreteStrategy<1> : public Strategy { ... };
Zmień klasę pomocnika, aby zarejestrować Strategy
s:
namespace StrategyHelper
{
template <int N> struct Initializer
{
Initializer()
{
getMap().Add(N, new ConcreteStrategy<N>());
}
};
}
Zmień kod w Strateg1.cpp na:
static StrategyHelper::Initializer<1> initializer;
Zmień kod w StrategN.cpp na:
static StrategyHelper::Initializer<N> initializer;