Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

25.03.2005, 22:32

Grafikmanager erweiterbar designen

Hi,

ich möchte für ein Spiel eine Art Grafikmanager (Texturmanager, Soundmanager...) bauen. Allerdings sollte dieser auch nach dem open-closed Prinzip designt sein. Das heißt mein aktueller Grafikmanager unterstützt noch kein 3D. Version zwei soll das aber können.
Es sieht im Moment folgendermaßen aus:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
class Graphic
{
public:
    Graphic(int width, int height, ...
    virtual void Some2DFunction(...);
    ...

private:
    int mWidth;
    int mHeight;
    ...
};


Angenommen ich möchte jetzt eine Graphic2-Klasse erstellen die sozusagen die alte Graphic-Klasse um 3D erweitert. Nur wie soll die alte und die neue Klasse dann designt sein? So?

Quellcode

1
2
3
4
5
6
7
8
9
10
11
class Graphic2 : public Graphic
{
public
    Graphic2(int Width, int Height, int ZBufferSize, int StencilBufferSize...
    virtual void Some3DFunction(...);
    ...

private:
    int ZBufferSize; 
    int StencilBufferSize;
};

Die alten 2D-Funktionen sollen weiterhin unterstützt werden von einem Graphic2 Objekt. Aber wie löse ich das mit den Memebervariablen? Soll jede abgeleitete Graphierweiterung dann seine eigenen mHeight und mWidth usw haben...? Auf welche Membervariablen greifen dann die alten 2D-Funktionen zurück? Konkrete Klassen von konkreten Klassen abzuleiten ist ja sowieso nicht gut, aber ich kann nunmal keine abstrakte Schnittstelle zur Verfügung stellen.
Wie kann man das sauber designen?

weigo

Treue Seele

Beiträge: 234

Wohnort: Deutschland

  • Private Nachricht senden

2

26.03.2005, 00:12

Irgenwie kommt mir der Thread von dem ZFX Board bekannt vor ;)
http://www.zfx.info/DisplayThread.php?TID=18998

3

26.03.2005, 01:25

Genau, allerdings hat dort niemand verstanden was ich meine. Kann hier vllt jemand helfen?

weigo

Treue Seele

Beiträge: 234

Wohnort: Deutschland

  • Private Nachricht senden

4

26.03.2005, 01:49

Wieso erstellst du nicht eine Interface Klasse, die nur das beinhaltet was jeder Grafikmanager benötigt, egal ob 2D oder 3D. Dann leidest du von diesem Interface z.B. zwei konkrete Klassen ab;

Quellcode

1
2
class Graphic2 : public IGraphic
class Graphic3 : public IGraphic

Im restliche Code arbeitest du nur mit dem Interface.
Zum Beispiel:

Quellcode

1
void CreateGraphicManager( IGraphic* pMgr );

Dieser Methode kannst du dann nach belieben eine konkrete Klasse bzw. Instanz übergeben. Brauchst du noch andere Formen z.B. 4D, dann leidest du einfach eine neue Klasse ab und brauchst den restlichen Code nicht anzufassen. Damit hast du auch dein OpenClose Prinzip.
Du kannst nur keine anderen Methoden durch IGraphic nutzen. Daher musst du ein allgemeines Interface finden und der Rest muss intern geschehen, z.B.:

Quellcode

1
2
3
4
5
6
7
8
9
10
class IGraphic
{
 public:
virtual ~IGraphic() { }

virtual void Create() = 0;
virtual void Shutdown() = 0;
virtual void WasAuchImmer() = 0;
// usw.
};


So funktioniert ein einfaches Interface System. Interface sind sehr nützlich und sollten die Lösung für dein Problem sein. Das hier war mehr ein abstraktes Beispiel.

Interface haben niemals Member Variablen. Daher musst du diese in jeder konkreten Klasse neu definieren. Aber das sollte kein großes Problem sein.

5

26.03.2005, 16:21

Aber genau da liegt mein Problem. Genau da!!!
Ich kann kein abstraktes Interface für die Idee "Grafikmanager" machen, weil ich doch nocht nicht weiß welche supertollen Funktionen mein Graphicmanager3 oder Garphicmanager5 haben wird. Wenn ich ein Interface erstelle, dann lege ich ja fest welche Funktionen alle abgeleiteten Graphicmanager haben. Wenn ich vorher schon weiß welche Funktionen die Graphicmanagerversionen haben werden, dann hätte ich das Problem ja garnicht. Aber es geht darum das die "neuen" Graphimanager, im Gegensatz zur alten Version neue Funktionen beinhalten, die alten aber noch unterstützzen sollen.

Anonymous

unregistriert

6

26.03.2005, 17:13

Ich mach dir mal ein Beispiel:
Du leitest jetzt also von IGraphic deine Grafikklasse ab, dann überschreibst du die Methoden in der IGraphic-Klasse. In der IGraphic-Klasse sollten natürlich nur Methoden stehen, die auch wirklich jeder Grafikmanager braucht, wie hier zum Beispiel Shutdown und Create. Den Rest der Funktionen kannst du dann einfach dazuschreiben.
Bsp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Graphic1 :IGraphic
{
public: 
//Überschriebene Methoden

    ~Grapfic1() { } 

    void Create(); 
    void Shutdown();

//Zugefügte Methoden

    bool Load3DModel(..);
    usw.
    
};


Wenn dir dann doch noch auffallt, dass dir eine Methode in der IGraphic fehlt, kannst du eine weiter abstrakte Klasse erstellen, die dann die abstrakten Methoden von IGraphic erbt und weitere hinzufügt.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

7

26.03.2005, 17:47

Die ganze Idee ist meiner Meinung nach ziemlich sinnlos, weil 2D- und 3D-Grafik nunmal was völlig Verschiedenes sind.

8

26.03.2005, 17:56

Zitat von »"Jo"«

Wenn dir dann doch noch auffallt, dass dir eine Methode in der IGraphic fehlt, kannst du eine weiter abstrakte Klasse erstellen, die dann die abstrakten Methoden von IGraphic erbt und weitere hinzufügt.

Wie soll das denn gehen? Dann ist das Prinzip der abstrakten Klassen ja dahin wenn ich gleich mehrere mache. Ich brauche da auch keine abstrakte Klassen, weil es einfach kein abstraktes Design für dieses Problem gibt. Eine abstrakte Klasse ist dafür da um (zB als Funktionargument) alle Abgeleiteten Objekte annehmen zu könnenund dann die jeweils richtige Methode aufzurufen. Das mache/brauche ich hier aber nicht. Es geht nur um Erweiterung.

Zitat von »"David Scherfgen"«

Die ganze Idee ist meiner Meinung nach ziemlich sinnlos, weil 2D- und 3D-Grafik nunmal was völlig Verschiedenes sind.

Nein. Es geht mir nur um die Erweiterung. Das war nur ein Beispiel. Warum versteht das denn niemand?

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

9

26.03.2005, 17:59

Zitat von »"Eruvae"«

Nein. Es geht mir nur um die Erweiterung. Das war nur ein Beispiel. Warum versteht das denn niemand?

Aus Deinem ersten Beitrag ist das aber nicht zu erkennen. Dort zeigst Du eine Klasse IGraphic und eine IGraphic2, die Du von der ersten ableitest. Wenn das nur Beispiele sind, woher sollen wir dann wissen, was Du eigentlich willst, und wie sollen wir Dir dann helfen können?

helium

Treue Seele

Beiträge: 180

Wohnort: NRW, Burscheid (nahe Köln)

  • Private Nachricht senden

10

26.03.2005, 19:31

Zitat

Die alten 2D-Funktionen sollen weiterhin unterstützt werden von einem Graphic2 Objekt. Aber wie löse ich das mit den Memebervariablen? Soll jede abgeleitete Graphierweiterung dann seine eigenen mHeight und mWidth usw haben...?

Nein.
guck dir mal "protected" an.
Why is 6 afraid of 7?
Because 7 8 9

Werbeanzeige