Katakanlah saya memiliki hirarki dari Item
kelas: Rectangle, Circle, Triangle
. Saya ingin dapat menggambar mereka, jadi kemungkinan pertama saya adalah menambahkan Draw()
metode virtual untuk masing-masing:
class Item {
public:
virtual ~Item();
virtual void Draw() =0;
};
Namun, saya ingin membagi fungsionalitas menggambar ke pustaka Draw yang terpisah sementara Core library hanya berisi representasi dasar. Ada beberapa kemungkinan yang dapat saya pikirkan:
1 - A DrawManager
yang mengambil daftar Item
s dan harus digunakan dynamic_cast<>
untuk mengetahui apa yang harus dilakukan:
class DrawManager {
void draw(ItemList& items) {
FOREACH(Item* item, items) {
if (dynamic_cast<Rectangle*>(item)) {
drawRectangle();
} else if (dynamic_cast<Circle*>(item)) {
drawCircle();
} ....
}
}
};
Ini tidak ideal karena bergantung pada RTTI dan memaksa satu kelas untuk mengetahui semua item dalam hierarki.
2 - Pendekatan lain adalah menunda menarik tanggung jawab ke ItemDrawer
hierarki ( RectangleDrawer
, dll):
class Item {
virtual Drawer* GetDrawer() =0;
}
class Rectangle : public Item {
public:
virtual Drawer* GetDrawer() {return new RectangleDrawer(this); }
}
Ini mencapai pemisahan kekhawatiran antara representasi dasar dari Item dan kode untuk menggambar. Masalahnya adalah bahwa kelas Item tergantung pada kelas menggambar.
Bagaimana saya bisa memisahkan kode gambar ini menjadi perpustakaan yang terpisah? Apakah solusi untuk Item mengembalikan kelas deskripsi dari pabrik? Namun, bagaimana ini dapat didefinisikan sehingga perpustakaan inti tidak bergantung pada perpustakaan undian?
sumber
visit()
metode ini.Perpecahan yang Anda jelaskan - menjadi dua hierarki paralel - pada dasarnya adalah pola jembatan .
Anda khawatir itu membuat abstraksi yang disempurnakan (Rectangle dll) bergantung pada implementasinya (RectangleDrawer), tapi saya tidak yakin bagaimana Anda bisa menghindarinya sepenuhnya.
Anda tentu dapat memberikan pabrik abstrak untuk memecah ketergantungan itu, tetapi Anda masih perlu beberapa cara untuk memberi tahu pabrik subclass mana yang akan dibuat, dan subclass itu masih tergantung pada implementasi yang disempurnakan khusus. Yaitu, bahkan jika Rectangle tidak bergantung pada RectangleDrawer, masih perlu cara untuk memberitahu pabrik untuk membangunnya, dan RectangleDrawer sendiri masih bergantung pada Rectangle.
Juga patut ditanyakan apakah ini abstraksi yang bermanfaat. Apakah menggambar persegi panjang begitu keras sehingga layak dimasukkan ke kelas differnt, atau apakah Anda benar-benar mencoba untuk abstrak perpustakaan grafik?
sumber
RectangleDrawer
,CircleDrawer
dll. Mungkin bukan cara yang paling berguna untuk abstrak perpustakaan grafik. Jika, sebaliknya, Anda mengekspos sekumpulan primitif melalui antarmuka abstrak biasa, Anda masih memutus ketergantungan.Lihatlah Polimorfisme Berbasis Semantik Nilai dan Konsep .
Karya ini telah mengubah cara saya memandang polimorfisme. Kami telah menggunakan sistem ini untuk memberikan pengaruh besar pada situasi yang berulang.
sumber
Alasan mengapa Anda mengalami masalah adalah karena benda tidak seharusnya menggambar sendiri. Menggambar sesuatu dengan benar tergantung pada satu miliar keping negara dan Rectangle tidak akan memiliki salah satu keping itu. Anda harus memiliki objek grafis sentral yang mewakili keadaan inti seperti backbuffer / depth buffer / shaders / etc, dan kemudian berikan metode Draw ().
sumber
Dog
atauCat
- objek yang bertanggung jawab untuk menggambar mereka jauh lebih kompleks daripada menggambar persegi panjang.