Masalah
Saya mengalami masalah sederhana, meskipun saya tidak dapat menemukan OOD yang tepat untuk masalah tersebut.
Apa yang saya punya:
- Kelas dasar
- Subkelas menambahkan metode baru
foo()
- Daftar pointer ke instance kelas dasar
Yang saya perlukan:
Saya perlu mengulang daftar ini dan memanggil foo()
untuk objek yang mendukung metode ini, yaitu objek dari (atau berasal dari) subkelas yang disebutkan di atas. Atau secara umum, saya memerlukan akses polimorfik "tidak berbau" ke subkelas melalui daftar pointer ke kelas dasar.
Contoh Kode
class Entity {
// ...
// This class contains methods also needed by subclasses.
};
class SaveableEntity : public Entity {
public:
virtual void save() = 0;
};
// SaveableEntity has multiple subclasses with specific save() implementations.
std::vector<Entity *> list;
for (Entity *entity : list) {
// Here I need to save() the descendants of a SaveableEntity type.
}
Saya mempunyai beberapa ide, namun tidak ada satupun yang menurut saya tepat. Berikut beberapa di antaranya:
Metode 1: dynamic_cast
Karena beberapa elemen dapat disimpan dan ada pula yang tidak, cara paling jelas yang saya lihat adalah transmisi dinamis:
std::vector<Entity *> list;
for (Entity *entity : list) {
auto saveable = dynamic_cast<SaveableEntity *>(entity);
if (saveable) {
saveable->save();
}
}
Namun, menggunakan dynamic_cast
sepertinya OOD yang buruk dalam situasi ini (koreksi saya jika saya salah). Selain itu, pendekatan ini dapat dengan mudah menyebabkan pelanggaran terhadap LSP.
Metode 2: Pindahkan save()
ke kelas dasar
Saya dapat menghapus SaveableEntity
dan memindahkan metode save()
ke basis Entity
. Namun, hal ini membuat kami menerapkan metode dummy:
class Entity {
virtual void save() {
// Do nothing, override in subclasses
}
};
Hal ini menghilangkan penggunaan dynamic_cast
, namun metode dummy tampaknya masih belum benar: sekarang kelas dasar menyimpan informasi (metode save()
) yang sama sekali tidak berhubungan dengannya.
Metode 3: Terapkan pola desain
- Pola Strategi: kelas
SaveStrategy
dan subkelasnya sepertiNoSaveStrategy
,SomeSaveStrategy
,SomeOtherSaveStrategy
, dll. Sekali lagi, kehadiranNoSaveStrategy
membawa kita kembali ke kelemahan metode sebelumnya: kelas dasar harus mengetahui detail khusus tentang subkelasnya, yang sepertinya desainnya buruk. - Pola Proxy atau Dekorator dapat dengan mudah merangkum
dynamic_cast
, namun ini hanya akan menyembunyikan kode yang tidak diinginkan, bukan menghilangkan desain buruk itu sendiri. - Tambahkan beberapa lapisan komposisi-over-warisan, dan seterusnya dan seterusnya...
Pertanyaan
Mungkin saya melewatkan beberapa solusi yang jelas, atau mungkin metode yang dijelaskan (1 atau 2) tidak seburuk dan berbau dalam konteks khusus ini seperti yang saya lihat.
Jadi pendekatan desain apa yang cocok dalam situasi seperti itu?