am 26. August 2009
Wenn ich mal in Fahrt bin, dann aber richtig. Nachdem wir und gestern das Entwurfsmuster Fassade ein wenig angeschaut haben, ist heute schon das nächste dran. Das Composite Pattern. Das schönste und einfachste Beispiel für dieses Muster ist, so finde ich zumindest, die Logger Klasse. Viele Systeme erlauben es genau einen Logger zu registrieren. Oft reicht dies aber nicht. Man würde gerne mehrere Logger auf einmal verwenden. Das lässt das System aber nicht zu.
Das heute im Fokus stehende Pattern erlaubt es eine Gruppe von Objekten so zu behandeln, als wäre es ein Einzelnes. Gehen wir aber am besten wieder mit einem Beispiel an die Sache ran:
interface iLogger
{
public function log( $message );
}
class SuperDuperFramework
{
private $logger;
// ...
public function registerLogger( iLogger $logger )
{
$this->logger = $logger;
}
public function doSthLogWorthy( )
{
$this->logger->log( 'Yihaaaaa' );
}
So dummerweise kann ich genau einen Logger an die Klasse übergeben. Auch wenn ich gerne mehrere registrieren würde, geht es nicht. Was aber machen? Ganz einfach: Das Kompositum Muster (klingt schrecklich der deutsche Name, oder?) anwenden. Wir brauchen also eine Klasse, die es uns ermöglicht diese Eindimensionalität zu durchbrechen.
class LoggerComposite implements iLogger
{
private $loggers = array( );
public function addLogger( iLogger $logger )
{
$this->loggers[] = $logger;
}
public function log( $message )
{
foreach( $this->loggers as $logger ) {
$logger->log( $message );
}
}
}
Eigentlich ganz einfach, was wir hier machen. Wir nehmen uns eine Klasse, die mit mehreren Loggern zurecht kommt, aber nach außen alle Eigenschaften eines Loggers hat, so das wir ihn überall auch als solchen verwenden können. Diesem Logger können wir jetzt ohne Probleme alle unsere Lieblingslogger übergeben und die werden dann nacheinander aufgerufen. Natürlich getriggert von unserem SuperDuperFramework.
Was wieder sehr schön an der Sache ist, dass wir das Framework nicht umgebaut haben. Es weiß also gar nicht, dass sich was geändert hat. So halten wir diese Multilogger-Komplexität vom Framework fern und können sie trotzdem nutzen.
Falls ihr selbst eine Klasse habt, die ihr mit einer Loggerfunktionalität bestücken wollt, dann könnt ihr euch ja überlegen, ob ihr es so lösen wollt oder doch die Multilogger-Fähigkeit gleich in die Klasse mit einbaut. Ich finde in unserem Fall die Composite Lösung elegangter, ist aber nur ein Bauchgefühl. Ich bin mir aber sicher, dass wir da gleich drüber diskutieren und ich am Ende des Tages eine Meinung haben werde.