Singleton fuer Dateizugriff?



  • Hallo!

    Ich moechte in einer Anwendung verschiedenen Klassen den Zugriff auf eine Datendatei ermoeglichen. Dazu wuerde ich gerne das Singleton-Pattern einsetzen.
    Leider habe ich damit (in C++) keinerlei Erfahrung und weiss nun nicht, wie ich den Zugriff auf die Datei in der Singleton-Klassen kapseln soll.

    Bisher habe ich das (quasi ein "Standard-Singleton"):

    class Daten
    {
        public:
            static Daten* instance();
    
        protected:
            Daten() {}
    
        private:
            /// Kopierkonstruktor privat deklarieren, damit nicht automatisch
            /// einer erstellt wird und Objekt nicht kopiert werden kann.
            Daten (const Daten&);
            static Daten* uniqueInstance;
    };
    
    Daten* Daten::uniqueInstance = 0;
    
    Daten* Daten::instance (void)
    {
        if (uniqueInstance == 0)
            uniqueInstance = new Daten();
    
        return uniqueInstance;
    }
    

    Jetzt muss ich ja nur noch irgendwie in der Daten-Klasse z.B. ein ifstream-Objekt erstellen und die Datei oeffnen, damit ich global daruf zugreifen kann, richtig? Wie koennte man das am geschicktesten machen?

    Danke fuer Hinweise!



  • Du öffnest das ifstream im Konstruktor und schließt es im Destruktur (der übrigens auch public sein sollte). Auf die Daten selbst lässt du mit Methoden zugreifen.

    BTW: Ich würde lieber Referenzen anstatt Zeiger benützen, aber gut.

    MfG SideWinder



  • SideWinder schrieb:

    Du öffnest das ifstream im Konstruktor und schließt es im Destruktur (der übrigens auch public sein sollte). Auf die Daten selbst lässt du mit Methoden zugreifen.

    Okay, danke. Doch so einfach 😉

    SideWinder schrieb:

    BTW: Ich würde lieber Referenzen anstatt Zeiger benützen, aber gut.

    Hmm, also dann so:

    class Daten
    {
        public:
            static Daten& instance();
            ~Daten();
    
        private:
            Daten() {}
            Daten (const Daten&);
    };
    
    Daten& Daten::instance (void)
    {
        static Daten uniqueInstance;
        return uniqueInstance;
    }
    
    [...]
    

    Welche Vorteile haette das genau? Oder ist das einfach eine "Geschmacksfrage"?

    Danke!



  • Ich bevorzuge diese Variante (Namentlich Meyers-Singleton) weil ich mich nicht um solche Probleme kümmern muss:

    delete singleton::getInstance(); // uff, der macht meinen zeiger kaputt
    

    MfG SideWinder



  • eberhard schrieb:

    Ich moechte in einer Anwendung verschiedenen Klassen den Zugriff auf eine Datendatei ermoeglichen. Dazu wuerde ich gerne das Singleton-Pattern einsetzen.

    Bitte bedenke dabei, dass für Singletons das selbe gilt wie für globale Variablen:
    ein Singleton ist solange schuldig bis seine unschuld zweifelsfrei und mit hieb und stichfesten Gründen bewiesen ist.

    Solange also nicht wirklich gute Gründe für ein Singleton sprechen (die Eigenschaft Singleton ist wirklich wirklich relevant, Code auf vielen verschiedenen logischen Ebenen muss die Dienste des Singletons in Anspruch nehmen...), solltest du lieber eine einfachere (und flexiblere) Implementation der Benutzbeziehung verwenden (z.B. Parameter).



  • HumeSikkins schrieb:

    Bitte bedenke dabei, dass für Singletons das selbe gilt wie für globale Variablen:
    ein Singleton ist solange schuldig bis seine unschuld zweifelsfrei und mit hieb und stichfesten Gründen bewiesen ist.

    Die von Dir angesprochenen Problematik mit Globals ist mir bewusst...

    HumeSikkins schrieb:

    Solange also nicht wirklich gute Gründe für ein Singleton sprechen (die Eigenschaft Singleton ist wirklich wirklich relevant, Code auf vielen verschiedenen logischen Ebenen muss die Dienste des Singletons in Anspruch nehmen...), solltest du lieber eine einfachere (und flexiblere) Implementation der Benutzbeziehung verwenden (z.B. Parameter).

    ... es handelt sich hier allerdings auch nicht um eine riesige, sicherheitsrelevante Applikation, sondern ich moechte mir einfach nur mal die verschiedenen Patterns ansehen und in C++ anwenden.

    So wie ich das sehe, hat das Singleton allerdings gegenueber Globals doch einen kleinen Vorteil: dadurch, dass man nicht direkt, sondern eben gekapselt ueber die Singleton-Klasse, auf die Daten zugreift, hat man ja immer noch eine gewisse Kontrollmoeglichkeit. Oder sehe ich das falsch?

    Benutzt Du fuer Objekte, die global benoetigt werden (z.B. Logger, Konfiguration, etc.) ausschliesslich die Uebergabe per Parameter an andere Objekte? Ist ja durchaus etwas muehsam, wenn man das durch evtl. X Ebenen reichen muss ... (bei einem perfekten Design sollte das natuerlich eigentlich gar nicht noetig sein ... 😉

    Danke fuer die Kommentare!



  • eberhard schrieb:

    Benutzt Du fuer Objekte, die global benoetigt werden (z.B. Logger, Konfiguration, etc.) ausschliesslich die Uebergabe per Parameter an andere Objekte?

    Nö. Ich halte es da wie Ward Cunningham:

    There is a proper context for every computation. So much of object-oriented programming is about establishing context, about balancing the lifetimes of variables, causing them to live the right length of time and then die gracefully. I'm not afraid of a few globals. They provide the global context that everyone must understand. There shouldn't be many though. Too many would scare me.

    Logger und Konfiguration (z.B. über eine Registry) gehören durchaus zum globalen Kontext. Der Punkt ist, dass man aufpassen muss, dass man den globalen Kontext nicht unnötig voll haut. Und Singleton ist ein Pattern, dass gerne mal genau dazu führt. Die von dir angesprochenen Vorteile eines Singletons gegenüber eine "normalen" globalen Variable dürfen nicht darüber hinwegtäuschen, dass es in den meisten Fällen einfachere und bessere Wege gibt als die Verwendung eines "global point of access".


Log in to reply