Vererbung mit Composite-Pattern
-
Hallo liebe Community,
ich habe nach Vorbild der GoF das Composite-Pattern implementiert. In meinem Fall heißt die Component-Klasse CTree, die Composites CNode und die Leafs CLeaf.
Ich habe diese in eine .lib kompiliert, um die Funktionalität dieses Patterns auch in anderen Projekten nutzen zu können - schließlich geht es in dem Buch ja auch um Wiederverwendung.Nun wollte ich das Pattern in einem neuen Projekt testen. Ich habe dazu eine Fensterklasse erstellt, welche als Vorlage für weitere spezielle Fenster dient und eine Handlerklasse, die diese Fenster verwalten kann. Beide Klassen sollen "Container-Funktionalität" besitzen und weitere Objekte aufnehmen können, daher erben Sie von CNode.
//COMPONENT class CTree { public: //Destruktor virtual ~CTree(); //Wird von geerbten Klassen deklariert virtual bool add(); virtual bool remove(); virtual std::list<CTree*>* getChildList(); protected: //Da der Konstruktor protected ist, können nur geerbte Klassen Instanzen erstellen (ist inaccessible) CTree(std::string); }; //COMPOSITE class CNode : public CTree { public: CNode(std::string=""); virtual ~CNode(); virtual bool add(CTree*); virtual bool remove(CTree*); virtual std::list<CTree*>* getChildList(); private: std::list<CTree*> _vComponents; }; //Fenster-Schablone class CBaseWindow : public CNode { public: void show(); void hide(); virtual ~CBaseWindow(); protected: //constructor (Titel, x, y, w, h, fullscreen, Farbe) CBaseWindow(std::string, int, int, int, int, bool, COLORREF); }; //Fenster-Handler class CWindowHandler : public CNode { public: CWindowHandler(); virtual ~CWindowHandler(); void showAllWindows(); };
Soweit zu den Klassen und nun zum eigentlichen Problem. Wenn ich nun Instanzen der CBaseWindow erzeuge, so verfügen diese über die Methoden von CNode wie bspw. add() und ihre eigenen wie show() und hide(). Nun erzeuge ich eine Instanz von CWindowHandler (erbt ebenfalls von CNode) und füge die gerade erzeugten Fenster-Instanzen per add() in den WindowHandler.
//Auszug aus main.cpp // Fenster-Instanzen erzeugen (Klassen CGuiWindow und COGLWindow erben von CBaseWindow) guiWnd = new CGuiWindow("Standard-Fenster", 0, 0, 50, 100, 0, RGB(255,255,255)); oglWnd = new COGLWindow("Standard-OpenGL-Fenster", 50, 50, 50, 50, 0, RGB(0,0,255)); //Fenster-Handler initialisieren wndhndl = new CWindowHandler(); wndhndl->add(guiWnd); wndhndl->add(oglWnd); //Zeige alle Fenster an wndhndl->showAllWindows();
Wenn ich nun aber in showAllWindows auf die Kindelemente zugreife, so verfügen diese nur noch über die Methoden der Klasse CNode. Es fehlen sozusagen die Methoden show() und hide().
//Implementierungs-Detail von showAllWindows void CWindowHandler::showAllWindows(){ //Elementliste (welche Fenster kennt Handler) std::list<CTree*>* i = getChildList(); //Methoden von CTree alle vorhanden (*i->begin())->add(); //geht //Methoden von CBaseWindow existieren nicht mehr (*i->begin())->show(); //geht nicht }
Ich habe es zwar mit einem dynamic_cast hinbekommen, will sowas aber nicht unbedingt verwenden.
//funktioniert, aber naja... dynamic_cast<CBaseWindow*>((*i->begin()))->show();
Also, habe ich nun die Verwendung des Composite-Patterns falsch verstanden und muss nun für alle "Container-Funktionalitäten" das Pattern neu schreiben oder habe ich einfach nur einen Denk- bzw. Designfehler? Ich freue mich über jeden guten Rat!
Gruß, ChillSn
-
ChillSn schrieb:
Also, habe ich nun die Verwendung des Composite-Patterns falsch verstanden
Ja, das sowieso.
Zu deinem Problem, du könntest versuchen, mit Templates zu arbeiten. Dein CBaseWindow könnte z.B. von CNode<CBaseWindow> ableiten. Das wäre das Curiously recurring template pattern. Wobei ich deinen Ansatz eh nicht so geschickt finde. Übertreib es nicht mit der Wiederverwendung, dazu war das Composite Pattern eher weniger gedacht
-
Danke für deine Antwort. Ich habe mir das alles noch mal durch den Kopf gehen lassen und verstehe jetzt auch, dass ich in eine völlig falsche Richtung gedacht habe. Ich habe dazu nochmal auf den ersten Seiten der GoF nachgelesen und bin auf einen Satz gestoßen, der mir einiges klar werden ließ: "Design Patterns are not about designs such as linked lists and hash tables that can be encoded in classes and reused as it. ... Design Patterns are descriptions ... that are customized...".
Scheinbar habe ich diese Aussage gekonnt überlesen^^
Wenn mein Englisch nicht völlig daneben ist, bedeutet das also für die Patterns, dass man die Idee zur Lösung eines Problems wiederverwenden sollte und nicht eine spezifische Implementierung davon, oder?
-
Ja, so in etwa kannst du dir das vorstellen.
Edit:
Vielleicht etwas ausführlicher Also, dass du für ein Window System das Composite Pattern einsetzt, ist schon richtig. Aber ich würde das Window System nicht auf einer generischen Baumstruktur aufbauen. Du musst für die konkrete Problemlösung auch weitere Kriterien, wie z.B. Typsicherheit, betrachten.