Disjunkte Klassen



  • Hallo Leute,

    ich stehe gerade vor einem Problem.

    Ich habe zwei Klassen die disjunkt sind und sozusagen nichts von einander wissen.

    Die eine ist ein OpenGL Frame, die zweite ist Interaktion mit der Maus und Keyboard.

    Ich möchte das beide sich untereinander verständigen, d.h wenn ich eine Maustaste drücke, soll Frame etwas ausgeben.

    Wie macht man sowas ohne Querverweise?

    Ist es überhaupt ein guter Stil?



  • Mein erster Gedanke ist eine Klasse die Frame und Interact beinhaltet und den beiden jeweils einen Zeiger auf das jeweilige Objekt setzt. Finde aber ein wenig.. naja.



  • Ich würde eine Art Singleton-Controller machen. Da rein holste dir jenachdem einfach die Instanzen der beiden Klassen. Die Attribute die untereinander ausgetauscht werden müssen, würde ich per Getter- und Setter() machen, solange es noch in einem absehbaren Rahmen ist... Da einem die Mausklicks usw. per Callback mitgeteilt werden, würde ich mir an deiner Stelle vielleicht mal Boost::Signal anschauen.

    Was auch noch eine Möglichkeit wäre, selbige Klasse herzunehmen und von beiden Anderen zu erben...

    Ich weiß aber nicht was du mit Querverweise meinst, hoffentlich nicht das was ich vorgeschlagen habe 🙂


  • Mod

    Wenn du es richtig super mit Zuckerguss haben möchtest, implementierst du ein Observer-Pattern. Keine Angst vor dem zunächst kompliziert aussehenden Link, das Grundmodell ist recht einfach umzusetzen (siehe das C++-Beispiel).

    edit: Und man sollte natürlich noch erwähnen, dass du nicht der erste wärst, der so etwas benötigt. Das heißt, wenn du nicht willst, musst du nicht selbst implementieren, wozu es schon zig Bibliotheken gibt.



  • Observer ist eine gute Möglichkeit.

    Oft kann man sich auch darauf beschränken dass ein Observable (in deinem Fall die Input-Klasse) nur einen einzigen Observer "kann". Das ist eine Spur einfacher und schneller zu implementieren.

    Anderer, ähnlicher Vorschlag: Die Input-Klasse bekommt Setter-Funktionen, mit denen man z.B. für jeden Event einen Funktor (-> boost::function<>) setzen kann.

    Ich persönlich würde allerdings die Variante "Observable" vorziehen.



  • Das könnte ungefähr so aussehen (mal schnell zusammenkopiert):

    class MouseListener
    {
    public:
    	virtual bool mouseMoved( const MouseEvent &arg ) = 0;
    	virtual bool mousePressed( const MouseEvent &arg, MouseButtonID id ) = 0;
    	virtual bool mouseReleased( const MouseEvent &arg, MouseButtonID id ) = 0;
    };
    
    class KeyListener
    {
    public:
    	virtual bool keyPressed( const KeyEvent &arg ) = 0;
    	virtual bool keyReleased( const KeyEvent &arg ) = 0;		
    };
    
    // Der Einfachheit halber
    class InputListener : public KeyListener, public MouseListener
    {
    };
    
    class Game
    {
    public:
    	void addInputListener( InputListener *l );
    	void removeInputListener( InputListener *l );
    
    private:
    	SomeContainer<InputListener *> m_listeners;
    	MyFrame *m_pFrame;
    }
    

    Die Interfaces Mouse- und KeyListener sind dazu da, die Benutzereingaben zu verarbeiten, die Klasse Game/Application hält alle "globalen" Variablen, also auch die für Input und das Fenster. Das funktionert jetzt so:
    - du überschreibst in InputListener die abstrakten Methoden und reagierst auf die Benutzereingaben
    - du fügst mittels Game::addInputListener neue Listener hinzu, etwa mittels m_listeners.append(l);
    - jedesmal, wenn du die Benutzereingaben erhälst (Fensterprozedur?), schickst du sie an Game. Dort werden sie an alle Input handler weitergegeben, die sich zuvor registriert haben.



  • Super!

    Danke für eure Hilfe 🙂


Anmelden zum Antworten