OOP-Designfrage



  • Die OO-Version von Callbacks läuft unter dem Namen Command Pattern.

    BTW:

    Man macht App zum Singleton

    Sprich: Du machst App global. Singleton löst nicht das Zugriffsproblem, die globale Variable löst es. Und die allseits bekannten Probleme von globalen Variablen verschwinden nicht, weil wir das jetzt Singleton nennen.

    fuez: Das Singleton Pattern wendet man an, wenn eine Klasse nur eine einzige Instanz haben soll. Siehe
    Design Patterns | ISBN: 0201633612



  • isbn Tag, keine schlechte Idee. Finde aber nen Link zu Amazon oder so einfacher 🤡

    Zum Singleton findet man auch was bei hume:

    http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=Singleton#Answ



  • Knuddlbaer schrieb:

    isbn Tag, keine schlechte Idee. Finde aber nen Link zu Amazon oder so einfacher 🤡

    Da das Buch eh auf meinem Schreibtisch liegt, ist es über die ISBN eindeutig einfacher 😉



  • Bashar schrieb:

    fuez: Das Singleton Pattern wendet man an, wenn eine Klasse nur eine einzige Instanz haben soll.

    aha...wieder was gelernt. 💡
    kann man das in C++ umsetzen? also eine klasse definieren, die nur 1 mal angelegt werden kann. ist da nicht eher eine lösung als modul angesagt. in C++ muss ja nicht alles eine klasse sein im gegensatz zu anderen sprachen (java).



  • fuez schrieb:

    kann man das in C++ umsetzen?

    Siehe Link den Knuddlbär gepostet hat.



  • Die OO-Version von Callbacks läuft unter dem Namen Command Pattern

    Warum so kompliziert? Eine virtuelle Methode eines Interfaces kann doch auch eine Form von callback sein. App könnte also z.B. von einer abstrakten Klassen MenuItem erben und sich dann bei Menu registrieren. Ähnlich dem Listener-Konzept von Java.

    Weniger Abhängigkeiten hat man, wenn man auf einen Signal-Slot-Mechanismus zurückgreift. Z.B. boost::signal:

    #include <iostream>
    #include <boost/signal.hpp>
    #include <boost/bind.hpp>
    using namespace std;
    class Menu
    {
    	typedef boost::signal0<void> OnButton;
    public:
    	OnButton buttonSlots_;
    	void onButtonClick()
    	{
    		buttonSlots_();
    	}
    
    };
    
    class App
    {
    public:
    	App()
    	{
    		m_.buttonSlots_.connect(boost::bind(&App::shutdown, this));
    	}
    	void shutdown()
    	{
    		cout << "Shut down" << endl;
    	}
    
    	Menu m_;
    };
    
    int main()
    {
    	App app;
    	app.m_.onButtonClick();
    }
    

    Das Beispiel ist natürlich übersimplifiziert.



  • Bashar schrieb:

    Und die allseits bekannten Probleme von globalen Variablen verschwinden nicht, weil wir das jetzt Singleton nennen.

    Immerhin die Synchronisationsprobleme können wir abschaffen, da wir die Möglichkeit haben, den Verwender des Singeltons dazu zu zwingen auf die Attribute über Methoden zuzugreifen, statt direkt auf das Attribut (wies bei gewöhnlichen globalen Variablen der Fall wäre)

    Die Tatsache, dass der Singelton dann selber global ist nicht mehr derart grob kritisch, solange Kon- und Destruktion des Selben klar geregelt werden.

    @Knuddlbaer Der Witz an den ISBN-Tags ist unter Anderem, dass du mit einem Klick auf den generierten Link - und natürlich anschliessendem Kauf - gleich automatisch das Forum etwas mitunterstützt, ohne, dass du extra noch irgendwie marcus' Referenz angeben, raussuchen etc. musst. ist also mit auch eine Begünstigung der Plattform hier von der wir ja alle profitiern können.

    -junix



  • Erstmal danke für die Antworten. 👍

    Aber nochmal ne andere Frage (wo wir gerade bei boost::signal sind):

    typedef boost::signal0<void> OnButton;
    public:
        OnButton buttonSlots_;
    

    @HumeSikkins: Hast du das Signal hier absichtlich public gemacht ?
    Ich meine, spricht hier etwas dagegen, so eine Signal-Membervariable public zu machen ?
    Afaik sind Membervariablen normalerweise private, damit die Klasse immer die Kontrolle über deren Manipulation hat (in den get/set-Methoden) und nicht einfach jemand einer Membervariablen einen unzulässigen Wert zuweist. Signals sind aber nur da, damit das Objekt ein Interface zum "anmelden" bereit stellt, der Klasse kann es egal sein, wer was damit macht, oder nicht? Ich sehe da keinen Grund Signals nicht einfach public zu machen. Was meint ihr ?



  • junix schrieb:

    @Knuddlbaer Der Witz an den ISBN-Tags ist unter Anderem, dass du mit einem Klick auf den generierten Link - und natürlich anschliessendem Kauf - gleich automatisch das Forum etwas mitunterstützt, ohne, dass du extra noch irgendwie marcus' Referenz angeben, raussuchen etc. musst. ist also mit auch eine Begünstigung der Plattform hier von der wir ja alle profitiern können.

    Draufklicken war zu einfach 🤡 Nu hab ich es auch verstanden O🤡



  • Kann mir einer sagen, was diese Zeile bewirkt:

    typedef boost::signal0<void> OnButton;
    

    Also wofür <> in dem Fall da ist.



  • Hast du das Signal hier absichtlich public gemacht ?

    Ich wollte nicht soviel tippen. Ist ja nur ein Beispiel.

    Ich sehe da keinen Grund Signals nicht einfach public zu machen. Was meint ihr ?

    Da C++ kein eingebautes Delegate-Konzept (wie C#) hat, sehe ich schon einen Grund für private: Wenn ich eine hübsche Register-Methode habe, kann ich zur Not den verwendeten Signal-Slot-Mechanismus austauschen. Auf der anderen Seite bereitet mir ein public-Signal im Moment auch keine wesentlichen Magenschmerzen.

    Strogij schrieb:

    Kann mir einer sagen, was diese Zeile bewirkt:

    typedef boost::signal0<void> OnButton;
    

    Also wofür <> in dem Fall da ist.

    boost::signal0 ist ein Template mit einem Parameter.
    Sowie:

    template <class T> class Foo {};
    

    Da wir hier einen Alias für eine konkrete Template-Instanz erstellen wollen, müssen wir den formalen Templateparameter von boost::signal0 durch einen aktuellen ersetzen.
    < leitet hier die Templateparameterliste ein, void ist der aktuelle Parameter für den Template-Parameter und > beendet die Templateparameterliste.

    Konkret ist der eine Parameter der Rückgabewert des kompatiblen Slots. In diesem Fall hat der passende Slot also keinen Rückgabewert. Außerdem auch keine Parameter.
    Funktionen wie:

    void func()
    

    oder Funktionsobjekte wie:

    struct Foo
    {
    void operator()() {}
    };
    

    sind also auf das Signal passende Slots.



  • Ahhh, daran habe ich gar nicht gedacht, stimmt, danke! 😉


Anmelden zum Antworten