Ich bin stark für die Strategie, die in der Antwort von @DocBrown beschrieben ist .
Ich werde eine Verbesserung der Antwort vorschlagen.
Die Anrufe
myMap.Add(1,new Strategy1());
myMap.Add(2,new Strategy2());
myMap.Add(3,new Strategy3());
kann verteilt werden. Sie müssen nicht zur selben Datei zurückkehren, um eine weitere Strategie hinzuzufügen, die dem Open-Closed-Prinzip noch besser entspricht.
Angenommen, Sie implementieren Strategy1
in der Datei Strategy1.cpp. Sie können den folgenden Codeblock darin haben.
namespace Strategy1_Impl
{
struct Initializer
{
Initializer()
{
getMap().Add(1, new Strategy1());
}
};
}
using namespace Strategy1_Impl;
static Initializer initializer;
Sie können denselben Code in jeder StategyN.cpp-Datei wiederholen. Wie Sie sehen können, wird dies eine Menge wiederholter Codes sein. Um die Codeduplizierung zu reduzieren, können Sie eine Vorlage verwenden, die in eine Datei eingefügt werden kann, auf die alle Strategy
Klassen zugreifen können.
namespace StrategyHelper
{
template <int N, typename StrategyType> struct Initializer
{
Initializer()
{
getMap().Add(N, new StrategyType());
}
};
}
Danach müssen Sie in Strategy1.cpp nur noch Folgendes verwenden:
static StrategyHelper::Initializer<1, Strategy1> initializer;
Die entsprechende Zeile in StrategyN.cpp lautet:
static StrategyHelper::Initializer<N, StrategyN> initializer;
Sie können die Verwendung von Vorlagen auf eine andere Ebene heben, indem Sie eine Klassenvorlage für die konkreten Strategieklassen verwenden.
class Strategy { ... };
template <int N> class ConcreteStrategy;
Und dann anstelle von Strategy1
verwenden ConcreteStrategy<1>
.
template <> class ConcreteStrategy<1> : public Strategy { ... };
Ändern Sie die Hilfsklasse, um Strategy
s zu registrieren, in:
namespace StrategyHelper
{
template <int N> struct Initializer
{
Initializer()
{
getMap().Add(N, new ConcreteStrategy<N>());
}
};
}
Ändern Sie den Code in Strateg1.cpp in:
static StrategyHelper::Initializer<1> initializer;
Ändern Sie den Code in StrategN.cpp in:
static StrategyHelper::Initializer<N> initializer;