C++-Programmierung: Entwurfsmuster: Singleton

Aus Wikibooks

Wechseln zu: Navigation, Suche

Inhaltsverzeichnis

[Bearbeiten] Singleton

Ein Singleton stellt sicher, dass genau ein Objekt einer Klasse instantiiert wurde (vgl. WikiBook Muster). Außerdem wird durch Singletons das Verwalten von globalen Variablen, die den selben Zweck erfüllen können, vermieden.

[Bearbeiten] Implementierung

Klassen, die das Singleton-Konzept implementieren, können entweder, wenn man nur wenige dieser Art braucht, immer neu geschrieben werden, oder auch mittels eines Templates generisch programmiert werden.

Ein Singleton wird instantiiert, wenn das erste Mal mit einer Funktion wie instance () ein Klassenobjekt angefordert wird. Ein Singleton, das dynamisch auf dem Heap-Speicher realisiert wurde, kann explizit zerstört werden, ansonsten existieren Singletons bis zum Programmende und verursachen damit Speicherlöcher (memory leaks).

[Bearbeiten] Normal (Heap)

 class N
 {
 public:
    static N* instance ()
    {
       static CGuard g;   // Speicherbereinigung
       if (!_instance)
          _instance = new N ();
       return _instance;
    }
    void xyz () {};
 private:
    static N* _instance;
    N () { }; /* verhindert, das ein Objekt von außerhalb von N erzeugt wird. */
              // protected, wenn man von der Klasse noch erben möchte
    N ( const N& ); /* verhindert, dass eine weitere Instanz via
 Kopie-Konstruktor erstellt werden kann */
    ~N () { };
    class CGuard
    {
    public:
       ~CGuard()
       {
          if( NULL != N::_instance )
          {
             delete N::_instance;
             N::_instance = NULL;
          }
       }
    };
    friend class CGuard;
 };
 N* N::_instance = 0; /* statische Elemente einer Klasse müssen initialisiert werden. */
/* Verwendung */
N::instance ()->xyz ();

[Bearbeiten] Normal (Stack)

 class N
 {
 public:
    static N& instance()
    {
       static N _instance;
       return _instance;
    }
    ~N() {};
    void xyz();
 private:
    N() {};           // verhindert, dass ein Objekt von außerhalb von N erzeugt wird.
                    // protected, wenn man von der Klasse noch erben möchte
    N( const N& ); /* verhindert, dass eine weitere Instanz via
 Kopier-Konstruktor erstellt werden kann */
    N & operator = (const N &); //Verhindert weitere Instanz durch Kopie
 };
/* Verwendung */
N& s = N::instance();
s.xyz();
//oder
N::instance().xyz();

[Bearbeiten] Template (Heap)

 template <typename C>
 class Singleton
 {
 public:
    static C* instance ()
    {
       if (!_instance)
          _instance = new C ();
       return _instance;
    }
    virtual
    ~Singleton ()
    {
       _instance = 0;
    }
 private:
    static C* _instance;
protected:
    Singleton () { }
 };
 template <typename C> C* Singleton <C>::_instance = 0;
 
/* Verwendung */
 class Test : public Singleton <Test>
 {
 friend class Singleton <Test>;
 public:
    ~Test () { };
    static Test* instance ()
    {
       return Singleton <Test>::instance ();
    }
    void xyz () { }
 protected:
    Test () : Singleton <Test> () { }
 };
 Test::instance ()->xyz ();

Der Konstruktor einer abgeleiteten Klasse muß immer den Konstruktor von Singleton aufrufen. Eine weitere Fehlerquelle ist das Weglassen des friend-Qualifizierers in der Klassendefinition abgeleiteter Klassen.

[Bearbeiten] Makro (Stack)

 #define DEF_SINGLETON( NAME )    \
 public:                        \
    static NAME& instance()      \
    {                            \
       static NAME _instance;    \
       return _instance;         \
    }                            \
 private:                       \
    NAME();               \
    NAME( const NAME& );
 
 /* Verwendung */
 class N
 {
    DEF_SINGLETON( N )
 public:
    void xyz();
 };
 ...
 N& s = N::instance();
 s.xyz();

Wikibooks buchseite.svg Zurück zu C++ Entwurfsmuster | One wikibook.svg Hoch zu C++ Entwurfsmuster | Wikibooks buchseite.svg Vor zu C++ Entwurfsmuster
Persönliche Werkzeuge