Vor ziemlich genau 100 Jahren hat der PHP Blogger mit einer Serie begonnen, die leider nie zum Ende gekommen ist: Es geht im Hook- und Callback Implementierungen. Teil 1 hat die eine Vererbungstechnik vorgestellt, in Teil 2 haben wir uns einen Callback-Stack angeschaut und weil mich ständig Fragen via Mail zu dem Thema erreichen, habe ich mich entschieden, den 3. Teil doch noch fertig zu stellen ;)
Im Teil 3 werfen wir also einen Blick auf die Listener-Objekte, wie sie in Actionscript zum Einsatz kommen. Die Actionscript-Götter haben mit den Listenern im Prinzip Callback-Pakete geschnürt: Alle zusammengehörigen Callback-Funktionen sind in einem Objekt untergebracht.
Ganz schön praktisch: Auf diese Weise kann man die sogenannten Listener öfter verwenden, muss sie aber nur ein Objekt im Speicher halten. Genau genommen sind Listener natürlich nur eine Abwandlung des Callback-Stacks (Link siehe oben), aber wie immer sind halt die Details entscheident: Im Gegensatz zum Callback-Stack werden die Callback-Funktionen direkt getriggert.
Werfen wir mal einen Blick auf eine Listener-Klasse:
class Listener
{
function onEvent()
{
// Mach irgendwas
}
}
Ein Objekt, dass diesen Listener verwenden könnte, sieht wie folgt aus:
class EventHost
{
var $eventListener;
function EventHost($pEventListener)
{
$this->eventListener= $pEventListener;
}
function triggerEvent()
{
$this->eventListener->onEvent();
}
}
Der Event-Listener könnte natürlich auch zur Laufzeit ausgetauscht werden. Und genau hier ist auch wieder der Decorator-Ansatz zu sehen. Statt Funktionen statisch in Klassen zu implentieren und durch die Gegend zu vererben, können Objekte Funktionen zur Laufzeit lernen.
In Programmiersprachen, die kompiliert werden, fällt ein solcher Vorteil natürlich noch stärker ins Gewicht. So wird aus einer schwerfälligen Applikation schnell ein Leichtfüssler.
Interessant wird es, wenn die Listener über Rückgabewerte verfügen. Im einfachsten Fall ein Boolean (true oder false). Was könnte man damit anstellen? Natürlich können wir ein solches Pattern dazu verwenden, Standard-Methoden zur Laufzeit beliebig zu überschreiben. Erweitern wir unseren Code erstmal um einen Default-Listener:
class DefaultListener
{
function onEvent()
{
// Macht nix
return false;
}
}
Wie man sehen kann, führt der Default-Trigger keine Aktion aus, er liefert lediglich false zurück. Jetzt erweitern wir den EventHost noch um ein paar Zeilen:
class EventHost
{
var $eventListener;
function EventHost()
{
$this->setEventListener(new DefaultListener());
}
function setEventListener($pEventListener)
{
$this->eventListener= $pEventListener;
}
function triggerEvent()
{
if(!$this->eventListener->onEvent())
{
// Mach Standard-Zeug
echo "Default";
}
}
}
Was hat sich geändert? Zunächst wird den Event-Listener nicht mehr im Konstruktor gesetzt, sondern über eine entsprechende Funktion “setEventListener”. Im Konstruktor wird der Default-Listener gesetzt, dessen Funktion false zurück liefert.
Sobald der Event getriggert werden soll, wird zunächst der Callback-Listener ausgeführt. Im Falle, das false zurückgeliefert wird, wird eine Standard-Methode ausgeführt. Wenn true zurück geliefert wird, passiert nichts.
Jetzt ein erweiterter Event-Listener:
class EventListener extends DefaultListener
{
function onEvent()
{
// Mach was besseres
echo "Endgeil";
// Lass es den EventHost wissen:
return true;
}
}
Wenn man jetzt folgenden Code ausführt…
$eventhost= new EventHost(); $eventhost->setEventListener(new EventListener); $eventhost->triggerEvent();
…erhält man aus Ausgabe “Endgeil!” statt “Default”. Warum muss ich jetzt nicht erklären, oder? Aber für was kann man sich so eine Logik zu nutze machen?
Prinzipiell ist es natürlich die beste Methodik, um es Usern zu erlauben, Frameworks oder Applikationen zu customizen. Ein Mechnismus kann so in nahe zu jede erdenkliche Richtung gebogen werden - ohne den Applikationskern verändern zu müssen.
Die Wordpress-Entwickler sind ein große Fans dieser Vorgehensweise und haben deshalb Actions und Filter großzügig eingesetzt, um Platz für Plugins und Themes zu machen.
Wenn Euch dieser Artikel gefallen hat, gibts demnächst noch einen 4. Teil, der auf die Platzierung von Filtern eingeht und Euch zeigt, wie man seine Applikation durch Filter flexibler machen kann.
Ähnliche Artikel:





