@DocBrown'un cevabında ana hatlarıyla verilen strateji lehine çok iyiyim .
Cevaba bir iyileştirme önereceğim.
Aramalar
myMap.Add(1,new Strategy1());
myMap.Add(2,new Strategy2());
myMap.Add(3,new Strategy3());
dağıtılabilir. Açık-Kapalı prensibine daha iyi uyan başka bir strateji eklemek için aynı dosyaya geri dönmek zorunda değilsiniz.
Strategy1
Strategy1.cpp dosyasında uyguladığınızı varsayalım. İçinde aşağıdaki kod bloğuna sahip olabilirsiniz.
namespace Strategy1_Impl
{
struct Initializer
{
Initializer()
{
getMap().Add(1, new Strategy1());
}
};
}
using namespace Strategy1_Impl;
static Initializer initializer;
Her StategyN.cpp dosyasında aynı kodu tekrarlayabilirsiniz. Gördüğünüz gibi, bu tekrarlanan kod çok olacak. Kod çoğaltmayı azaltmak için, tüm Strategy
sınıfların erişebileceği bir dosyaya yerleştirilebilecek bir şablon kullanabilirsiniz .
namespace StrategyHelper
{
template <int N, typename StrategyType> struct Initializer
{
Initializer()
{
getMap().Add(N, new StrategyType());
}
};
}
Bundan sonra, Strategy1.cpp'de kullanmanız gereken tek şey:
static StrategyHelper::Initializer<1, Strategy1> initializer;
StrategyN.cpp dosyasında ilgili satır:
static StrategyHelper::Initializer<N, StrategyN> initializer;
Somut Strateji sınıfları için bir sınıf şablonu kullanarak şablonların kullanımını başka bir seviyeye taşıyabilirsiniz.
class Strategy { ... };
template <int N> class ConcreteStrategy;
Ve sonra, yerine Strategy1
kullanın ConcreteStrategy<1>
.
template <> class ConcreteStrategy<1> : public Strategy { ... };
S'yi kaydetmek için yardımcı sınıfı değiştirin Strategy
:
namespace StrategyHelper
{
template <int N> struct Initializer
{
Initializer()
{
getMap().Add(N, new ConcreteStrategy<N>());
}
};
}
Strateg1.cpp içindeki kodu şu şekilde değiştirin:
static StrategyHelper::Initializer<1> initializer;
StrategN.cpp'deki kodu şu şekilde değiştirin:
static StrategyHelper::Initializer<N> initializer;