Design Patterns in PHP - Teil 5: Das Vererbte Singleton-Factory-Registry Pattern

Wenn man die drei Design Patterns aus den vorangegegangen Artikeln kombiniert, bekommt man sowas wie ein "Vererbtes Singleton-Factory-Registry". Dieses "Pattern" setze ich momentan erfolgreich als Basis des Refactoring/Redesigns meines kleinen Frameworks openWebX2 ein.



Als Basis dient hier eine erweiterte Version unserer abstrakten Singleton-Klasse:


  1. <?php
  2. abstract class SingletonFactoryRegistry {
  3.  
  4. 	// Instanzen werden in einem statischen Array gespeichert -> Registry
  5. 	private static $instances = array();
  6.  
  7. 	// Wie immer die Singleton-Vorraussetzungen:
  8. 	protected function __construct() {}
  9. 	final private function __clone() {}
  10.  
  11. 	// Die um Parameter erweiterte Singleton-Instanz
  12. 	final static public function getInstance($mixedParams = NULL) {
  13. 		static $instances = NULL;
  14. 		$myHash = md5(serialize($mixedParams));
  15. 		return $instances[$myHash] ?: $instances[$myHash] = new static($mixedParams);
  16. 	}
  17.  
  18. 	// Der "Loader", welcher sicherstellt, dass Objekte korrekt 
  19. 	// instanziiert werden, entweder via Singleton oder via Konstruktor.
  20. 	// Diese Instanzen werden dann gespeichert.
  21. 	// Also eine Art Factory-Registry
  22. 	final static public function load($strObject, $mixedParams = NULL) {
  23. 		$strObjectHash = md5($strObject.serialize($mixedParams));
  24. 		if (!isset(self::$instances[$strObjectHash])) {
  25. 			// Wenn das Objekt den Singleton benutzt, dann wird es via getInstance
  26. 			// instanziiert, ansonsten via Konstruktor.
  27. 			self::$instances[$strObjectHash] = (method_exists($strObject, 'getInstance') 
  28. 												? $strObject::getInstance($mixedParams) 
  29. 												: new $strObject($mixedParams));
  30. 			}
  31. 		return self::$instances[$strObjectHash];
  32. 	}
  33. }
  34. ?>




Dieses Object können wir nun benutzen um beliebige Objekte zu "laden". Wir legen uns dazu erst mal 2 unterschiedliche Klassen an:


  1. <?php
  2.  
  3. // Object benutzt das Singleton-Pattern
  4. class mySingleton extends SingletonFactoryRegistry {
  5.  
  6. 	private $__id = NULL;
  7.  
  8. 	// Der Constructor kann einen Parameter bekommen
  9. 	protected function __construct($strID = NULL) {
  10. 		$this->__id = $strID;
  11. 	}
  12. }
  13.  
  14. // Dieses Object hat einen normalen Konstruktor
  15. class myStandard {
  16.  
  17. 	private $__id = NULL;
  18.  
  19. 	public function __construct($strID = NULL) {
  20. 		$this->__id = $strID;
  21. 	}
  22. }
  23. ?>




Wir können nun beide Arten von Objekten über die load Methode unserer "SingletonFactoryRegistry"-Klasse instanziieren:


  1. <?php
  2. $myObj1 = SingletonFactoryRegistry::load('mySingleton');
  3. $myObj2 = SingletonFactoryRegistry::load('myStandard');
  4.  
  5. // Parameter:
  6. $myObj3 = SingletonFactoryRegistry::load('mySingleton','1');
  7. $myObj4 = SingletonFactoryRegistry::load('myStandard','2');
  8.  
  9. // Nun testen wir ob das SingletonFactoryRegistry-Pattern funktioniert:
  10.  
  11. $myObj5 = SingletonFactoryRegistry::load('mySingleton','1');
  12. $myObj6 = SingletonFactoryRegistry::load('myStandard','2');
  13.  
  14. var_dump($myObj1);
  15. var_dump($myObj2);
  16. var_dump($myObj3);
  17. var_dump($myObj4);
  18. var_dump($myObj5);
  19. var_dump($myObj6);
  20. ?>




Wie erwartet, sehen wir, dass $myObj3 und $myObj5 ebenso auf das identische Objekt verweisen wie $myObj4 und $myObj6:


  1. object(mySingleton)#1 (1) { ["__id":"mySingleton":private]=>  NULL }
  2. object(myStandard)#2 (1) { ["__id":"myStandard":private]=> NULL }
  3. object(mySingleton)#3 (1) { ["__id":"mySingleton":private]=> string(1) "1" }
  4. object(myStandard)#4 (1) { ["__id":"myStandard":private]=> string(1) "2" }
  5. object(mySingleton)#3 (1) { ["__id":"mySingleton":private]=> string(1) "1" }
  6. object(myStandard)#4 (1) { ["__id":"myStandard":private]=> string(1) "2" } 




Wir haben uns somite eine Art Object-Cache gebaut, der momentan noch innerhalb eines Prozesses seine Grenzen findet. Interessant wäre aber die Möglichkeit, die Objekte persistent zu speichern. Dieses nehmen wir in den nächsten Folgen unserer kleinen Serie in Angriff ;-)




Jens

Neuen Kommentar schreiben

Plain text

  • Keine HTML-Tags erlaubt.
  • Internet- und E-Mail-Adressen werden automatisch umgewandelt.
  • HTML - Zeilenumbrüche und Absätze werden automatisch erzeugt.