Ankündigung

Einklappen
Keine Ankündigung bisher.

Gegenstück zu parent:: oder Singleton abstrakt implement. ??

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Gegenstück zu parent:: oder Singleton abstrakt implement. ??

    Hi,

    hab mal ne kleine Frage, und zwar habe ich Klassen, die ich mit Singleton instanzier. Dazu schreibe ich jedes Mal in den Klassenkopf die Singleton vars+methoden.

    Jetzt habe ich probiert, die Singleton-Implementation in die Elternklasse auszulagern:

    In der abstrakten Klasse steht dann irgendwie sowas in der Art

    PHP-Code:
        // Singleton
        // $className var defines the current classname for the singleton pattern
        // and needs to be overridden in the concrete one
        
        #protected  static  $className;
        
    static $instance;
        
        static function 
    getInstance () 
        {    
            if (!isset(
    $instance)) self::$instance = new child::$className;
            return 
    self::$instance;
        }
        
    // Singleton END 
    Da ich zum instanzieren der eigentl. Klasse aber den Namen brauche, muss der ja in der konkreten Kind Klasse stehen.

    Dachte das iss ja einfach und hab wollt die var $className überschreiben, was aber nicht geht.
    Statische Vars lassen sich nämlich nicht überschreiben...

    Was ich jetzt suche ist ne Möglichkeit, dass wenn in der Parent-Klasse getInstance() aufgerufen wird, dass ich auf ne Var von der Kind-Klasse zugreifen kann.
    Für die Elternklasse gibts ja parent:: aber ein derivat für die Kindklasse dazu habe ich leider nicht gefunden.

    Würde mich freuen wenn jmd einen Tipp hätte, hab echt keine Lust überalle den Singleton-Schmudder immer in den Klassen zu haben

    gruß melchior
    MF goes Melchior


  • #2
    Du musst den Code ja nicht in die Kind-Klasse schreiben, aber du kannst das ganze ja von dort aus anstossen und dabei eben die Eigenschaft des Kindes übergeben.

    Ein child:: o.ä. kenne ich nicht, das heißt aber nicht, dass es das nicht gibt.

    Klingt aber etwas nach Design-Fehler.

    Kommentar


    • #3
      ne child gibts nicht, das stimmt - war nur code von verschiedene trials :P
      hab ja geschr. dass es nur so vom prinzip aussehen muss

      das mit den "antriggern" hatte ich mir auch schon überlegt - fand es aber etw. unsauber.

      Falls es halt keine andere Lösung gibt, muss ich es wohl so machen

      gracie
      melchior
      MF goes Melchior

      Kommentar


      • #4
        Worum gehts denn konkret bei den Klassen bzw. dem singleton?
        (aus reinem Interesse, keine Belehrung geplant)

        Kommentar


        • #5
          hehe ok, wenns keine Belehrung ist

          Arbeite mit dem Zend Framework, das auf dem mvc-pattern basiert. Also Trennung von Models, Controller und Views.

          Meine Models präsentieren die Datenschicht, die ja von der DB gelesen werden muss. Desw. hab ich mir ne eigene abstrakte Klasse geschrieben, die das Handling dafür übernimmt (executeSql, getNumhits, changeCounter usw). Die Klasse wird dann im in den einzelnen Models extended.

          Da alle Models nur einmal existieren mach ich das mim Singleton. Vom Framework selbst gibts zwar auch nen objektspeicher, aber da müsste ich immer nachschauen ob schon eins existiert. Da ich knapp 30 Models hab, hab ich relativ wenig Lust um das Management zu kümmern.

          gruß
          m

          ps: zend framework anschauen, wenn noch nicht getan!
          MF goes Melchior

          Kommentar


          • #6
            Benutze Zend auch und hatte eigentlich nie das Problem, dass ich zweimal ein Model instanziere Also jetzt mal aus der Praxis heraus lohnt sich das an den Punkt recht wenig. Ich lad mein Model direkt per new in der abstrakte Controller-Klasse und sicher es in ein Property. Da ja eh nur der Controller interesse am Model hat, reicht das Den Rest sauber programmieren und eben nicht das Model ein zweites mal instanzieren (hat in View oder Model eh nix zu suchen) und das passt scho.

            Warum eigentlich? Ich vermisse sonst den Konstruktor
            Nicht jeder Fehler ist ein Bug.

            Kommentar


            • #7
              Hallo Melchior,

              hierzu ist es ratsam eine abstrakte Singlton-Klasse zu implementieren, die die Aufgaben für dich übernimmt und einen Singleton-Cache definiert.
              Dazu kann ich dir folgenden Code zeigen (kommentare habe ich entfernt; ist eine PHP 4 Implementierung). Anwenden tust du das dann in deinem Code mit


              PHP-Code:
              $oMgr = &Singleton::getInstance('myManager'); ?> 
              Hier der Code:

              PHP-Code:
                 class Singleton
                 
              {

                    
              pfunction Singleton(){
                    }


                    function &
              getInstance($className){

                       
              // Prüfen, ob Instanz des Objekt bereits existiert
                       
              if(!Singleton::isInSingletonCache($className)){

                          
              // Erzeugt Klasse $className singleton
                          
              $GLOBALS[Singleton::showCacheContainerOffset()][Singleton::createCacheObjectName($className)] = new $className;

                        
              // end if
                       
              }

                       
              // Gibt Instanz aus Singleton-Cache zurück
                       
              return $GLOBALS[Singleton::showCacheContainerOffset()][Singleton::createCacheObjectName($className)];

                     
              // end function
                    
              }


                    function 
              isInSingletonCache($className){

                       if(isset(
              $GLOBALS[Singleton::showCacheContainerOffset()][Singleton::createCacheObjectName($className)])){
                          return 
              true;
                        
              // end if
                       
              }
                       else{
                          return 
              false;
                        
              // end else
                       
              }

                     
              // end function
                    
              }


                    function 
              createCacheObjectName($className){
                       return 
              strtoupper($className);
                     
              // end function
                    
              }


                    function 
              showCacheContainerOffset(){
                       return (string)
              'SINGLETON_CACHE';
                     
              // end function
                    
              }

                  
              // end class
                 
              }
              ?> 
              Have fun!
              Viele Grüße,
              Dr.E.

              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
              1. Think about software design before you start to write code!
              2. Discuss and review it together with experts!
              3. Choose good tools (-> Adventure PHP Framework (APF))!
              4. Write clean and reusable software only!
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

              Kommentar


              • #8
                Ich möchte das Thema nochmal ausbuddeln, um meine frisch gebackene php5 Singleton Variante zur Diskussion zu stellen.
                Ziel war es, die Singleton Funktionalität weitgehend in eine eigene Klasse auszulagern, die auch die Instanzen vorhält. Da mir die Variante Singleton::createInstance (SingletonName [, Args ]); nicht so richtig gefällt, habe ich die Kindklasse mit einer Methode getInstance () ergänzt, so dass über den Klassennamen selbst ebenfalls eine Singleton-Instanz erzeugt werden kann. Es gibt also zwei Möglichkeiten, ein neues Singletonobjekt zu erzeugen.
                Der Konstruktor der Kindklasse wird quasi als Presetting Methode mißbraucht.

                PHP-Code:
                <?

                class Singleton 
                  {
                  # -- numerisches Array aus Singleton Objekten
                  private static $aUniqueInstances = array ();

                  protected function __construct () {}
                  private final function __clone () {}

                  public static final function createInstance ()
                    {
                    $aArguments = func_get_args ();

                    # -- 1. Argument ist Klassenname, weitere werden an Konstruktor übergeben
                    $sClassname = array_shift ($aArguments);

                    # -- für den Fall, dass Singleton (nichtstatische) Methoden nutzen soll:
                    #    ohne Klassennamen-Attribut die Singleton Klasse selbst instanzieren
                    if (NULL === $sClassname) $sClassname = 'Singleton';

                    # -- Referenz auf Singleton Objekte, wenn NULL neue Instanz erzeugen
                    $oInstance = & self::$aUniqueInstances[$sClassname];
                    if ($oInstance === NULL) 
                      {
                      $oInstance = new $sClassname;

                      # -- __construct der Klasse aufrufen, um darin definierte Presettings 
                      #    auszuführen, genutzt werden die Attribute, die der Methode
                      #    createInstance () übergeben werden
                      if (true === method_exists ($oInstance , '__construct'))
                        call_user_func_array (array (& $oInstance , '__construct') , $aArguments);
                      }

                    return ($oInstance);
                    }

                  }



                class TestSingleton extends Singleton
                  {
                  public $iRandom = 0;
                  private $iSetting = 0;
                  
                  protected function __construct ($iSetting = 0) 
                    {
                    # -- doppeltes Setting unterbinden
                    if (0 === func_num_args ()) return;

                    $this->iRandom = rand ();
                    $this->iSetting = $iSetting;
                    }

                  public static function getInstance ($iSetting = 0)
                    {
                    return (Singleton::createInstance (__CLASS__ , $iSetting));
                    }


                  function test ()
                    {
                    echo $this->iSetting;
                    }

                  }


                // Instanz über getInstance der Klasse
                $a = TestSingleton::getInstance (5);
                $b = TestSingleton::getInstance (12);
                // Instanz über Singleton Klasse
                $c = Singleton::createInstance ('TestSingleton' , 8);

                // Das würde in einem Fatal error enden
                // $d = new TestSingleton (6); 
                // Ebenso
                // $d = clone $c;

                // Zum Test, ob alle Variablen ein Objekt referenzieren
                $c->iRandom = '0815';

                TestSingleton::getInstance ()->test ();
                Singleton::createInstance ('TestSingleton')->test ();

                print_r($b);
                print_r($a);
                print_r($c);
                Wie gesagt, frisch geschrieben. Anregungen sind willkommen.
                --

                „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                --

                Kommentar


                • #9
                  Hallo nikosch77,

                  Initialisierungen von singleton instanziierten Klassen sollte man tunlichst von der Erzeugung trennen, da es sonst kein echtes abstract Singleton ist. Zudem musst du bei deiner Klasse unterscheiden zwischen "create class" und "get reference", was die Implementierung umständlicher macht.

                  Das Thema Initialisierung habe ich in meinem Framework in das "coreObject" eingebaut. Mit der Methode "createAndInitServiceObject()" kann man sich eine Applikations-Schicht oder eine Klasse singleton instanziieren und gleichzeitig initialisieren lassen, sofern die Klasse eine init()-Methode hat. So ist transparent, dass dort eine Singlton-Instanz zurückkommt egal ob ich eine erzeugt habe oder nur eine Referenz zurückgebe inkl. Initialisierung.
                  Viele Grüße,
                  Dr.E.

                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  1. Think about software design before you start to write code!
                  2. Discuss and review it together with experts!
                  3. Choose good tools (-> Adventure PHP Framework (APF))!
                  4. Write clean and reusable software only!
                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                  Kommentar


                  • #10
                    Danke. Ich bin mir nicht sicher, ob ich Deine Hinweise vollständig verstanden habe. Meinst Du, dass man S-Instanzen prinzipiell nie initialisieren soll (wie es hier in __construct() geschieht, prizipiell aber meinetwegen auch in einer init() Methode passieren könnte)? Wenn ich Dich recht verstehe, wiederspricht es dem Prinzip der Abstraktion, weil die Singleton Klasse nicht 'wissen' kann, welche Initfunktion die implementierende Klasse bereitstellt?
                    Es ergibt sich bei meiner Lösung aber ein Vorteil. Da die Singleton Klasse die einzelnen S-Objekte verwaltet, weiß sie allein, welche bereits existieren. Rufe ich an verschiedenen, voneinander unabhängigen Stellen meiner Applikation die Singletonverwaltung für ein gewünschtes Objekt mit gleichen Initialisierungsparametern auf, so kann bei Instanzierung einmalig initialisiert werden und die anderen Fälle erhalten schlicht eine Referenz auf das Objekt. Ansonsten muß ich immer erst ermitteln, ob eine Instanz existiert, dann die Referenz holen und initialisieren. Ich hoffe Du kannst nachvollziehen was ich meine.

                    Ich habe nur die getAndInitServiceObject() Methode gefunden, ich denke Du meinst diese? Die Idee ist nicht schlecht, mein bisheriges 'Framework' besaß ein Application-Objekt, dass mir meine Singletons bereitgestellt und initialisiert hat. Na mal sehen. Die obige Lösung schien mir naheliegend, weil eine normale Klasse durch die Erweiterung mit extends Singleton und durch das Setzen des Konstruktors auf protected einfach zur Singleton konvertiert werden kann. Die bisherige Initialisierung bleibt dabei gleich, da bei Instanzierung über die createInstance() Methode bisherige Initvariablen einfach durchgereicht werden.

                    Zitat von dr.e.
                    Zudem musst du bei deiner Klasse unterscheiden zwischen "create class" und "get reference", was die Implementierung umständlicher macht.
                    Was meinst Du damit? In beiden möglichen Instanzierungsmöglichkeiten
                    PHP-Code:
                    $object Classname::getInstance (); 
                    bzw.
                    PHP-Code:
                    $object Singleton::createInstance ('Classname'); 
                    wird immer eine Referenz zurückgegeben, egal ob das Objekt frisch instanziert wurde oder bereits im Array $aUniqueInstances (bei Dir heißt das Cache) existierte.
                    Ich bin gespannt auf Deine Antwort. Mein Ziel ist eben eine abstrakte Umsetzung des Singleton Patterns in php5, ohne auf GLOBALS ausweichen zu müssen, wie es Dein Framework tut.
                    --

                    „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                    Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                    --

                    Kommentar


                    • #11
                      Wenn ich Dich recht verstehe, wiederspricht es dem Prinzip der Abstraktion, weil die Singleton Klasse nicht 'wissen' kann, welche Initfunktion die implementierende Klasse bereitstellt?
                      Richtig. Die abstrakte Singleton Implementierung sollte nichts von Parametern wissen, da du sonst Abhängigkeiten erzeugst, die "Wissen" voraussetzen. Hierzu sollte man eine weitere Abstraktions-Schicht einziehen.


                      Es ergibt sich bei meiner Lösung aber ein Vorteil. Da die Singleton Klasse die einzelnen S-Objekte verwaltet, weiß sie allein, welche bereits existieren. Rufe ich an verschiedenen, voneinander unabhängigen Stellen meiner Applikation die Singletonverwaltung für ein gewünschtes Objekt mit gleichen Initialisierungsparametern auf, so kann bei Instanzierung einmalig initialisiert werden und die anderen Fälle erhalten schlicht eine Referenz auf das Objekt. Ansonsten muß ich immer erst ermitteln, ob eine Instanz existiert, dann die Referenz holen und initialisieren. Ich hoffe Du kannst nachvollziehen was ich meine.
                      Das eine schließt das andere nicht aus. Irgendwo in der Applikation Singleton aufzurufen und eine Singleton-Instanz zu bekommen ist ein Feature, das man der abstrakten Singleton-Implementierung mitgeben sollte. Sie verwaltet einen Cache und hält dort bereits initialisierte Klassen, die bei Bedarf wieder zurückgegeben werden können. Auf der anderen Seite möchte man natürlich auch initialisierte Objekte haben. Das kann man dadurch lösen, dass man einfach ein Objekt singleton instanziiert, anschließend initialisiert und beim nächsten Aufruf einfach so verwendet. Man kann diese Logik z.B. in der init()-Methode mitgeben, dass sichergestellt ist, dass das Objekt nur einmal initialisiert ist. Drumrum kann man - wie ich das getan habe - eine weitere Kapselung schaffen, damit das holen einer Referenz und das Initialisieren nur eine Code-Zeile bedeutet, oder man schreibt zwei Zeilen, wenn man kein einheitliches Interface für eine Initialisierung hat.

                      Der zweite Fall ist der, dass man unterschiedlich initialisierte Objekte gleicher Klasse haben möchte. Für diesen Fall sollte das Factory (bestmöglich Abstract Factory) oder das Builder-Pattern verwendet werden. Hier kann man einfach eine Singleton-Instanz der konkreten Factory (bei mir gibt es sowas bei meinem Pager) ziehen und diese wiederum verwaltet die konkreten Instanzen des Objekts (Pager), je nach Initialisierungs-Parameter. Bei einer abstrakten Factory wird das etwas diffizieler, denn dort muss man generisch die Verwaltung der initialisierten Objekte implementieren.


                      Was meinst Du damit? In beiden möglichen Instanzierungsmöglichkeiten

                      PHP-Code:
                      1
                      <?php $object = Classname::getInstance ();


                      bzw.

                      PHP-Code:
                      1
                      <?php $object = Singleton::createInstance ('Classname');


                      wird immer eine Referenz zurückgegeben, egal ob das Objekt frisch instanziert wurde oder bereits im Array $aUniqueInstances (bei Dir heißt das Cache) existierte.
                      Du hast dabei das Problem, dass du bei der Implementierung darauf achten musst, was du aufrufst. Das ist einfach zu "unzuverlässig". Verwende am besten nur eine Variante und diese durchgängig, dann wir das auch besserlesbarer.


                      Ich bin gespannt auf Deine Antwort. Mein Ziel ist eben eine abstrakte Umsetzung des Singleton Patterns in php5, ohne auf GLOBALS ausweichen zu müssen, wie es Dein Framework tut.
                      Was heißt hier "ausweichen"? Irgendwo musst du ja deinen Singleton-Cache verwalten. Ob du das nun in $GLOBALS machst - ich verwende sogar noch einen generischen Offset - oder sonstwo ist (eigentlich) egal. Fakt ist, dass du einen Cache brauchst, sonst fällt die Verwaltung flach, oder PHP "weiß" nicht mehr, wo das Objekt gerade ist.
                      Viele Grüße,
                      Dr.E.

                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                      1. Think about software design before you start to write code!
                      2. Discuss and review it together with experts!
                      3. Choose good tools (-> Adventure PHP Framework (APF))!
                      4. Write clean and reusable software only!
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                      Kommentar


                      • #12
                        Vielen Dank. Alle Unklarheiten beseitigt. Ausweichen war nicht im negativen Sinne gemeint, es ist mir klar, dass unter php4 keine andere Variante als die über GLOBALS möglich ist. Ich finde aber gerade die Möglichkeit, eine Objektreferenz als Klassenvariable der verwendeten Klasse zu speichern sehr elegant. Allerding habe ich das für eine abstrakte Singletonimplementierung nicht mehr umsetzen können und bin auf das Array als Klassenvariable der Singleton Klasse ausgewichen.
                        --

                        „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                        Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                        --

                        Kommentar


                        • #13
                          Hallo nikosch77,

                          Alle Unklarheiten beseitigt.
                          Freut mich.


                          Allerding habe ich das für eine abstrakte Singletonimplementierung nicht mehr umsetzen können und bin auf das Array als Klassenvariable der Singleton Klasse ausgewichen.
                          Poste die Lösung bei Gelegenheit mal. Der Code würde mich interessieren.
                          Viele Grüße,
                          Dr.E.

                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                          1. Think about software design before you start to write code!
                          2. Discuss and review it together with experts!
                          3. Choose good tools (-> Adventure PHP Framework (APF))!
                          4. Write clean and reusable software only!
                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                          Kommentar


                          • #14
                            Hallo, vielleicht noch nicht ganz perfekt, aber ich habe einige der Ratschläge beherzigt. Ich weiß nicht, ob bspw. destroyInstance () in die Factory mit hineingehört, ebenso wenig ob eine Factory die Produkte je nach Auswertung deren Elternklasse erzeugen sollte, aber naja. Ist ja erst Version 0.1.

                            Das was mich immer noch stört sind die eval () Angaben, wie in http://www.phpfriend.de/forum/ftopic62401.html beschrieben.

                            PHP-Code:
                            <?


                            /*

                                              Modul               Singleton
                                              Autor               (C) Nico Streuber
                                              Versionsgeschichte
                                                Version 0.1       2007-07-26
                                                                                                          */

                              # ----------------------------------------------------------------------------
                              #  KLASSE     AbstractSingleton
                              # ----------------------------------------------------------------------------

                             /*

                                Abstrakte Klasse, die grundlegende Singleton Methoden bereitstellt. Durch 
                                die protected final Methoden __construct und __clone werden für alle abge-
                                leiteten Klassen direkte Instanziierung und das Klonen eines bereits instan-
                                ziierten Objektes unmöglich.
                                Eine Singleton-Instanziierung erfolgt über die statische Methode 
                                createInstance (), die Instanz wird für jede Kindklasse in deren statischer 
                                Property $oInstance gespeichert.

                              öffentliche Methoden:

                                void     = ::createInstance (string classname)
                                void     = ::destroyInstance (string classname)
                                & object = ::getInstanceReference (string classname)
                                                                                                          */

                            abstract class AbstractSingleton 
                              {
                              /*
                              void = protected __construct (void)

                                Konstruktor. Durch Deklaration als protected wird die direkte Instanziierung
                                einer von AbstractSingleton abgeleiteten Klasse verhindert (es sei denn 
                                die Klasse definiert einen eigenen public Konstruktor)

                                Wurde bewußt nicht als finale gesetzt, um abgeleiteten Klassen bspw. 
                                statische Initialisierungen durch die Definition eigener Konstruktoren
                                zu ermöglichen
                              --------------------------------------------------------------------------- */
                              protected function __construct () {}



                              /*
                              void = protected __clone (void)

                                Clone Methode. Durch Deklaration als protected wird das Erstellen der Kopie
                                einer Objektinstanz einer von AbstractSingleton abgeleiteten Klasse 
                                verhindert

                                finale Methode, kann nicht redefiniert werden
                              --------------------------------------------------------------------------- */
                              final protected function __clone () {}



                              /*
                              void = public::createInstance (string classname)

                                Methode erzeugt bei Bedarf (d.h. bei Nichvorhandensein eines entsprechenden
                                Objektes) eine Singleton Instanz der Klasse mit dem in classname angegebenen
                                Namen. Das erzeugte Objekt wird im Klassenmember der jew. Klasse gespeichert

                                finale Methode, kann nicht redefiniert werden
                              --------------------------------------------------------------------------- */
                              final public static function createInstance ($sClassname)
                                {
                                # -- Fehler: angeforderte Klasse nicht-existent
                                if (false === class_exists ($sClassname))
                                  return (new ApplicationError);

                                # -- Referenz auf Klassenmember der Singleton Kindklasse
                                eval ('$oInstance = & ' . $sClassname . '::$oInstance;');

                                # -- wenn NULL neue Instanz erzeugen, in Member ablegen
                                if ($oInstance === NULL) $oInstance = new $sClassname;
                                }



                              /*
                              void = public::destroyInstance (string classname)

                                Methode löscht eine Singleton Instanz, indem sie das zugehörige 
                                Klassenmember auf NULL setzt

                                finale Methode, kann nicht redefiniert werden
                              --------------------------------------------------------------------------- */
                              final public static function destroyInstance ($sClassname)
                                {
                                # -- Fehler: angeforderte Klasse nicht-existent
                                if (false === class_exists ($sClassname))
                                  return (new ApplicationError);

                                # -- Referenz auf Klassenmember der Singleton Kindklasse
                                #    und Klassenmember auf Null setzen

                                eval ('$oInstance = & ' . $sClassname . '::$oInstance;');
                                $oInstance = null;
                                }



                              /*
                              & object = public::getInstanceReference (string classname)

                                Methode liest eine Singleton Instanz aus dem Klassenmember der Klasse, deren
                                Name in classname angegeben ist und gibt eine Referenz auf den Inhalt dieses
                                Members zurück

                                finale Methode, kann nicht redefiniert werden
                              --------------------------------------------------------------------------- */
                              final public static function & getInstanceReference ($sClassname)
                                {
                                # -- Fehler: angeforderte Klasse nicht-existent
                                if (false === class_exists ($sClassname))
                                  return (new ApplicationError);

                                # -- Referenz auf Klassenmember der Singleton Kindklasse
                                #    und diese zurückgeben

                                eval ('$oInstance = & ' . $sClassname . '::$oInstance;');
                                return ($oInstance);
                                }

                              }


                              # ----------------------------------------------------------------------------
                              #  KLASSE     AbstractPlainSingleton
                              # ----------------------------------------------------------------------------

                             /*

                                Abstrakte Klasse, die ein abgeleitete Singleton Klasse als nicht 
                                initialisierbar kennzeichnet.
                                                                                                          */

                            abstract class AbstractPlainSingleton extends AbstractSingleton
                              {
                              }


                              # ----------------------------------------------------------------------------
                              #  KLASSE     AbstractInitializedSingleton
                              # ----------------------------------------------------------------------------

                             /*

                                Abstrakte Klasse, die ein abgeleitete Singleton Klasse als initialisierbar 
                                kennzeichnet . Die Initialiserung kann bei der Instanziierung über die 
                                Factoryklasse durch Angabe des Namens der Init-Methode und Übergabe der 
                                nötigen Werte als Parameter erfolgen.
                                                                                                          */

                            abstract class AbstractInitializedSingleton extends AbstractSingleton
                              {
                              }


                              # ----------------------------------------------------------------------------
                              #  KLASSE     Singleton (Factory)
                              # ----------------------------------------------------------------------------

                             /*

                                Factory Klasse, die durch Übergabe eines Klassennamens versucht, davon ein
                                Objekt Singleton abzuleiten. Vorher wird geprüft, ob die benannte Klasse von
                                der abstrakten Klasse AbstractSingleton abgeleitet ist.
                                Besitzt die zu instanziierende Klasse eine Initfunktion und ist sie von der 
                                abstrakten Klasse AbstractInitializedSingleton abgeleitet, können auch 
                                direkt Initialisierungsparameter mit übergeben werden.

                              öffentliche Methoden:

                                & object = ::getInstance (string classname [, string method [, mixed attribute , ...]])
                                void     = ::destroyInstance (string classname)

                              Hinweis:

                                Um ein Löschen aller Referenzen auf eine Singletonklasse zu gewährleisten 
                                muß die Zuweisung einer von getInstance gelieferten Objekt-Referenz an die 
                                Variable immer über & erfolgen.
                                                                                                          */

                            class Singleton
                              {
                              /*
                              & object = ::getInstance (string classname [, string method [, mixed attribute , ...]])

                                Methode die ein Singleton-Objekt der namentlich übergebenen Klasse erstellt 
                                und/oder eine Referenz darauf zurückliefert.
                                Von AbstractInitializedSingleton oder einer Kindklasse abgeleitete Klassen 
                                können durch Angabe des Namens der Initfunktion und weiterer Parameter bei 
                                Instanziierung initialisiert werden. 
                                
                                Achtung! Die Initfunktion wird auch bei weiteren Anforderungen der 
                                Objektreferenz ausgeführt (es obliegt also der entspr. Methode eine 
                                Neuinitialisierung zu verhindern)
                              --------------------------------------------------------------------------- */
                              public static 
                              function & getInstance ($sClassname , $sInitMethod = 'init')
                                {
                                $aArguments = func_get_args ();

                                # -- 1. Argument ist Klassenname, 2. Name der Initfunktion
                                $sClassname = array_shift ($aArguments);
                                $sInitMethod = array_shift ($aArguments);


                                # -- Fehler: kein Singleton-Child
                                if (false === is_subclass_of ($sClassname , 'AbstractSingleton'))
                                  {
                                  return (new ApplicationError);
                                  }

                                # -- Fehler: fehlende Objekt-Erzeugungsmethode
                                #    dürfte nicht vorkommen, da Singleton diese Methode abstract vorschreibt
                                if (false === method_exists ($sClassname , 'createInstance'))
                                  return (new ApplicationError);


                                switch (true)
                                  {
                                  # -- Singletonklasse mit Initialisierungsmethode zurückgeben
                                  case true === is_subclass_of ($sClassname , 'AbstractInitializedSingleton'):
                                    $oReference 
                                      = & self::getInitSingleton ($sClassname , $sInitMethod , $aArguments);
                                    return ($oReference);


                                  # -- sonstig geartete Singletonklasse zurückgeben
                                  case true === is_subclass_of ($sClassname , 'AbstractPlainSingleton'):
                                  default:
                                    $oReference = & self::getPlainSingleton ($sClassname);
                                    return ($oReference);
                                  }
                                }



                              /*
                              void = ::destroyInstance (string classname)

                                Löscht eine Singleton Instanz, indem sie die gleichnamige Methode der 
                                abstrakten Basisklasse AbstractSingleton aufruft
                              --------------------------------------------------------------------------- */
                              public static 
                              function destroyInstance ($sClassname)
                                {
                                AbstractSingleton::destroyInstance ($sClassname);
                                }



                              # ----------------------------------------------------------- Hilfsmethoden --

                              /*

                              & object = private ::getInitSingleton (string classname , string method , array attributes)

                                Hilfsmethode, die eine AbstractInitializedSingleton Kindklasse instanziiert
                                und/oder die Instanz zurückliefert und initialisiert
                              --------------------------------------------------------------------------- */
                              private static 
                              function & getInitSingleton ($sClassname , $sInitMethod , $aArguments)
                                {
                                # -- Objekt ableiten
                                AbstractSingleton::createInstance ($sClassname);
                                $oReference = & AbstractSingleton::getInstanceReference ($sClassname);
                                do
                                  {
                                  # -- Instanziierung fehlgeschlagen, Fehler durchreichen
                                  if ($oReference instanceof ApplicationError) break; 

                                  # -- keine Initmethode angegeben, keine Intialisierung
                                  if (true === empty ($sInitMethod)) break;

                                  # -- Intialisieren
                                  call_user_func_array (array ($oReference , $sInitMethod) , $aArguments);
                                  }
                                while (false);

                                return ($oReference);
                                }



                              /*

                              & object = private ::getPlainSingleton (string classname)

                                Hilfsmethode, die eine AbstractPlainSingleton Kindklasse instanziiert 
                                und/oder diese Instanz zurückliefert
                              --------------------------------------------------------------------------- */
                              private static 
                              function & getPlainSingleton ($sClassname)
                                {
                                # -- Objekt ableiten
                                AbstractSingleton::createInstance ($sClassname);
                                $oReference = & AbstractSingleton::getInstanceReference ($sClassname);

                                return ($oReference);
                                }
                              }







                            class TestSingleton extends AbstractInitializedSingleton
                              {
                              protected static $oInstance = null;
                              protected $bInitDone = false;

                              public $iRandom = 0;
                              private $iSetting = 0;

                              function init ($iSetting = 0)
                                {
                                if (true === $this->bInitDone) return (false);

                                $this->iRandom = rand ();
                                $this->iSetting = $iSetting;

                                return ($this->bInitDone = true);
                                }

                              }



                            class TestNoSingleton
                              {
                              }



                            $a = & Singleton::getInstance ('TestSingleton');
                            $b = & Singleton::getInstance ('TestSingleton' , 'init' , 12);

                            // liefert ApplicationError, da keine Singleton Kindklasse
                            // $c = & Singleton::getInstance ('TestNoSingleton');



                            var_dump ($a , $b);

                            Singleton::destroyInstance ('TestSingleton');

                            var_dump ($a , $b);
                            AbstractSingleton stellt die grundlegenden ST Methoden für alle Kindklassen. Ein hinreichendes Kriterium, um eine Klasse als Singleton zu kennzeichnen ist die Ableitung aus einer der Kindklassen von AbstractSingleton und die Definition eines statischen Members $oInstance, das die Referenz auf die Instanz aufnehmen kann.
                            .
                            --

                            „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                            Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                            --

                            Kommentar

                            Lädt...
                            X