OOP stilfrage...
-
ok, sagen wir mal, ich programmiere für ein system, für das ich funktionen zwecks grafikausgabe, input etc. erst selbst schreiben muss.
mein erster gedanke war, einfach eine singleton-klasse, zb. "System", zu erstellen, denn schliesslich gibt es ja immer nur ein system. nun stellt sich mir hierbei das problem, dass ich eigentlich von dieser klasse auch andere klassen ableiten müsste/möchte, wie zb. sprites etc, also hardware-nahe sachen, die zwingend auf eine "System"-klasse angewiesen sind. nun lässt sich aber von einem singleton natürlich nicht ohne weiteres eine andere klasse ableiten (korrigiert mich...). wie könnte ich also sonst noch vorgehen? einfach in den entsprechenden klassen voraussetzen, dass eine klasse "System" existiert und darauf zugreifen (bei einem singleton ja kein problem)? oder für "System" statt einer klasse einfach nur einen namespace nehmen und diesen voraussetzen?ich weiss, solche stilfragen sind nicht gerade beliebt, aber ich will gerade diesen programmteil absolut sauber durchziehen, da er ja die grundlage für alle weiteren programme sein soll und sicher auch noch oft geändert/erweitert wird...
-
wenn du den konstruktor von system protected machst, kannst du auch von dieser klasse ableiten.
-
ein sprite ist doch kein system, deswegen finde ich hier vererbund ungeeignet.
ein sprite kann doch auf ein singelton system zugreifen
-
Vererbung wuerd ich auch nicht einsetzen... Da schon eher vorraussetzten, dass es immer ein "System" gibt... oder, was ich noch besser finde (aber teilweise nur schwer realisierbar ist):
Immer, wenn ein Objekt oder eine Funktion aus "System" benoetigt wird, das einfach uebergeben... z. B. wenn eine Klasse in einer seiner Methoden etwas aus System benoetigt, dann uebergib "System" einfach als Parameter an die Methode....
Oder, was IMO vom Design her noch ein Quaentchen besser waere: "System" klingt nach einer riesigen Klasse, deshalb waere es sinnvoll, diese eine Klasse in mehrere kleine Klassen (z. B. "Input", "Video", usw.) aufzuteilen, und diese dann entweder in einem namespace "system" oder eben auch einer Singleton-Klasse namens System unterzubringen....
Dein Anwendungscode koennte dann in etwa so aussehen:
/* * KLASSEN, DIE ZU "SYSTEM" GEHOEREN: * ################################## */ class Video { // .... }; class System { public: static System* getSingleton; // erstelle Singleton // ... Video* Video(); // damit kannst du auf die "Video" Komponente des Systems zugreifen // .... private: System(); // ... }; #define SYSTEM System::getSingleton // kleiner Hack, um singletons angenehmer zu verwenden :) /* * KLASSEN, DIE "SYSTEM" VERWENDEN: * ################################## */ class Sprite { // ... void draw(Video* Videodevice); }
Dann sieht ein Aufruf einer solchen Funktion in etwa so aus:
Sprite fooBar; fooBar.draw(SYSTEM->Video);
So hab jedenfalls ich das Problem geloest, als ich das letztemal vor so einem Design-Problem gestanden hab
-
Dimah schrieb:
ein sprite ist doch kein system, deswegen finde ich hier vererbund ungeeignet.
ein sprite kann doch auf ein singelton system zugreifensprites gehören schon zum system, da sie in hardware unterstützt werden.
aber gut, werd ich halt ein singleton nehmen...
-
maximAL schrieb:
sprites gehören schon zum system, da sie in hardware unterstützt werden.
das ist aber keine "ist ein" bezeihung, ist ein sprite ein system?
Blue-Tiger schrieb:
#define SYSTEM System::getSingleton // kleiner Hack, um singletons angenehmer zu verwenden :)
na ob du dadurch den code leichter verständlich machst, System::getSingleton ist wie ein kleine docu für mich
es sagt mir das es nur eine instanz gibt, es sagt mir das sie vom typ system ist usw.und dann würde ich vorschlagen:
class Sprite { // ... void draw(Video* Videodevice); public: void setVideo(Video* Videodevice); static Video * Videodevice; } Video * Sprite::Videodevice = NULL; //irgend wo einmal in code Sprite::setVideo( System::getSingleton().Video() ); Sprite fooBar; fooBar.draw();
ich würde ein kolaps kriegen wenn ich bei jeder draw methode das ausgabe medium übergeben sollte und es wäre doch dumm wenn du jetzt das medium weckseln willst (dafür machen wir doch das ganze) dann noch an 100 stellen code ändern
-
Dimah schrieb:
ich würde ein kolaps kriegen wenn ich bei jeder draw methode das ausgabe medium übergeben sollte und es wäre doch dumm wenn du jetzt das medium weckseln willst (dafür machen wir doch das ganze) dann noch an 100 stellen code ändern
vorrausgesetzt das "Video"-Modul ist gut designt sollte es kein Problem sein, das Medium zu wechseln ohne den Anwendercode mitzuwechseln.... Ausserdem: was machst du, wenn du irgendwann mal 2 Ausgabegeraete gleichzeitig ansprechen willst (vielleicht auch nur, um 2 Bereiche auf dem Bildschirm anzusprechen, oder 2 Monitore, oder sonstwas)? Ok, das ist jetzt nicht sehr wahrscheinlich, aber koennte ja sein
(einigen wir ins auf "es ist Geschmacksache", ok?
)
maximAL schrieb:
sprites gehören schon zum system, da sie in hardware unterstützt werden.
eine oeffentliche Vererbung bedeutet wie Dimah schon gesagt hat "ist ein", und ein Sprite ist nun mal kein System, es ist hoechstens Teil eines Systems...
IMO ist ein namespace fuer eine solche Beziehung besser geeignet
-
Da es ja eine Stilfrage ist:
Eine Vererbung einzuführen, um sich Tipparbeit zu sparen, ist gaaanz schlechter Stil, und Pickel bekommt man davon auch.eine "Sprite.Draw(Video)" wird zwar in OOP-Kursen gerne verwendet, ist aber auch Pickelverdächtig. Um Sprite.Draw zu implementieren, muß entweder Sprite die Interna von Video kennen, oder Video muß eine recht umfangreiche Schnittstelle zur Verfügung stellen.
Besser ist es da, Sprite zu einem "passiven" Datenobjekt zu machen (d.h. Sprite enthält Sprite-Daten, und Methoden, um diese Daten zu manipulieren), und Video.Draw(sprite) zu verwenden. Hier hast du zwar im prinzip das gleiche Problem - Video muß die interna von Sprite kennen - aber das ist i.a. einfacher zu bewerkstelligen als andersherum.
Wenn du Flexibilität in beiden Richtungen brauchst - also völlig unbekannte Video-Dingens, und völlig unbekannte Sprite-Dingens, sollte die Draw-Methode eine Brücke sein: Draw(Video, Sprite). Fir spezielle Video/Sprite-Kombinationen können dann optimierte Draw-Methoden zur Verfügung gestellt werden. Das ist aber i.a. overkill.
jetzt zum Video, auf das du malst:
Mit einer globalen Variable ist es immer einfacher - solange man halt wirklich bloß eine davon hat. Bei "System" ist das noch halbwegs einzusehen, aber schon bei "Video" wäre ich vorsichtig.
Üblicherweise wirst du ja sowieso entweder RenderScene-Methoden, oder ein Scene-Objekt haben, den kann man das Ziel-Video-Objekt als Parameter bzw. als Member mitgeben.
-
#define SYSTEM System::getSingleton // kleiner Hack, um singletons angenehmer zu verwenden
Da geibts einen noch viel einfacheren Trick:
System & system = System::getSingelton();
Draw(Video, Sprite). Fir spezielle Video/Sprite-Kombinationen können dann optimierte Draw-Methoden zur Verfügung gestellt werden. Das ist aber i.a. overkill.
Zumal du ein Doubledispatcher bauen musst.
-
Helium schrieb:
#define SYSTEM System::getSingleton // kleiner Hack, um singletons angenehmer zu verwenden
Da geibts einen noch viel einfacheren Trick:
System & system = System::getSingelton();
das wollte ich im ersten augenblick vorschlagen, aber damit verliert mal einen der vorteile von singetons und zwar das sie nur instanziert werden wenn sie gebraucht werden
also benutzen kann man das schon, aber nicht in den Header von System
-
Aber in Funktionen, in denen man ein Singleton häufig braucht.