Pattern sind eine Möglichkeit, um optimale Verfahren und gute Entwürfe zu beschreiben. Sie zeigen eine flexible Lösung für verbreitete Programierprobleme.
Das Factory-Pattern erlaubt die Instanziierung von Objekten zur Laufzeit. Es wird Factory-Pattern genannt, weil es für die "Herstellung" eines Objektes zuständig ist. Eine parametrisierte Factory bekommt den Namen der zu instanziierenden Klasse als Parameter übergeben.
Beispiel #1 Parametrisierte Factory-Methode
<?php
class Example
{
// Die parametrisierte Factory-Methode
public static function factory($type)
{
if (include_once 'Drivers/' . $type . '.php') {
$classname = 'Driver_' . $type;
return new $classname;
} else {
throw new Exception('Treiber nicht gefunden');
}
}
}
?>
Wenn diese Methode in einer Klasse definiert wird, erlaubt sie dieser, Treiber bei Bedarf zu laden. Wenn die Example-Klasse eine Datenbankabstraktionsklasse wäre, könnte das Laden eines MySQL- und SQLite-Treibers wie folgt aussehen:
<?php
// Lade einen MySQL Treiber
$mysql = Example::factory('MySQL');
// Lade einen SQLite Treiber
$sqlite = Example::factory('SQLite');
?>
Das Singleton stellt sicher, dass es nur eine Instanz einer Klasse geben kann; es stellt eine globale Zugriffsmöglichkeit zu dieser Instanz bereit. Singleton ist ein Pattern der "Gang of Four".
Das Singleton-Pattern wird oft implementiert in Datenbankklassen, Loggern, Front-Controllern oder Request- und Response-Objekten.
Beispiel #2 Singleton-Funktion
<?php
class Beispiel
{
private static $instance;
private $count = 0;
private function __construct()
{
}
public static function singleton()
{
if (!isset(self::$instance)) {
echo 'Erstelle neue Instanz.';
$className = __CLASS__;
self::$instance = new $className;
}
return self::$instance;
}
public function increment()
{
return $this->count++;
}
public function __clone()
{
trigger_error('Clonen ist nicht erlaubt.', E_USER_ERROR);
}
public function __wakeup()
{
trigger_error('Deserialisierung ist nicht erlaubt.', E_USER_ERROR);
}
}
?>
Illustrated below is how the Singleton behaves
<?php
$singleton = Example::singleton(); // gibt "Erstelle neue Instanz." aus
echo $singleton->increment(); // 0
echo $singleton->increment(); // 1
$singleton = Example::singleton(); // verwendet die bereits existierende Instanz
echo $singleton->increment(); // 2
echo $singleton->increment(); // 3
// alle folgenden Zeilen führen zu einem Fatal Error
$singleton2 = new Example;
$singleton3 = clone $singleton;
$singleton4 = unserialize(serialize($singleton));
?>
Das Singleton-Pattern ist eines der kontrovers betrachteten Pattern. Kritiker argumentieren, dass Singletons zu globale Zuständen in Applikationen führen und dass sie das Singleton und die benutzenden Klassen eng koppeln. Somit entstehen versteckte Abhängigkeiten und unerwartete Seiteneffekte, woraus wiederum Code entsteht, der schwierig zu testen und zu warten ist.
Die Kritiker argumentieren außerdem, dass es sinnlos ist, ein Singleton in einer Shared-Nothing-Architektur wie PHP einzusetzen, in der Objekte nur innerhalb eines Requests eindeutig sind. Es ist einfacher und sauberer, Kollaborations-Objektgraphen zu erstellen, indem die Builder- und Factory-Pattern am Anfang eines Requests benutzt werden.
Singletons verstoßen außerdem gegen die "SOLID"-OOP-Design-Regeln und gegen das Gesetz von Demeter. Singletons können nicht serialisiert werden. Sie können nicht durch Subtypen ersetzt werden (vor PHP 5.3) und sie werden auch nicht bei der Garbage-Collection berücksichtigt, weil die Instanz als statisches Attribut des Singletons gespeichert wird.