Saya sangat mendukung strategi yang dijabarkan dalam jawaban oleh @DocBrown .
Saya akan menyarankan peningkatan jawaban.
Panggilan
myMap.Add(1,new Strategy1());
myMap.Add(2,new Strategy2());
myMap.Add(3,new Strategy3());
dapat didistribusikan. Anda tidak harus kembali ke file yang sama untuk menambahkan strategi lain, yang menganut prinsip Open-Closed lebih baik.
Katakanlah Anda menerapkan Strategy1
dalam file Strategy1.cpp. Anda dapat memiliki blok kode berikut di dalamnya.
namespace Strategy1_Impl
{
struct Initializer
{
Initializer()
{
getMap().Add(1, new Strategy1());
}
};
}
using namespace Strategy1_Impl;
static Initializer initializer;
Anda dapat mengulangi kode yang sama di setiap file StategyN.cpp. Seperti yang Anda lihat, itu akan menjadi banyak kode berulang. Untuk mengurangi duplikasi kode, Anda bisa menggunakan templat yang bisa dimasukkan ke dalam file yang dapat diakses oleh semua Strategy
kelas.
namespace StrategyHelper
{
template <int N, typename StrategyType> struct Initializer
{
Initializer()
{
getMap().Add(N, new StrategyType());
}
};
}
Setelah itu, satu-satunya hal yang harus Anda gunakan di Strategy1.cpp adalah:
static StrategyHelper::Initializer<1, Strategy1> initializer;
Baris yang sesuai di StrategyN.cpp adalah:
static StrategyHelper::Initializer<N, StrategyN> initializer;
Anda bisa menggunakan templat ke level lain dengan menggunakan templat kelas untuk kelas Strategi konkret.
class Strategy { ... };
template <int N> class ConcreteStrategy;
Dan kemudian, alih-alih Strategy1
, gunakan ConcreteStrategy<1>
.
template <> class ConcreteStrategy<1> : public Strategy { ... };
Ubah kelas pembantu untuk mendaftar Strategy
menjadi:
namespace StrategyHelper
{
template <int N> struct Initializer
{
Initializer()
{
getMap().Add(N, new ConcreteStrategy<N>());
}
};
}
Ubah kode di Strateg1.cpp ke:
static StrategyHelper::Initializer<1> initializer;
Ubah kode di StrategN.cpp ke:
static StrategyHelper::Initializer<N> initializer;