Nehmen wir also an, Sie möchten das Observer-Muster nicht, da Sie Ihre Klassenmethoden ändern müssen, um die Aufgabe des Abhörens zu bewältigen, und etwas Allgemeines wünschen. Angenommen, Sie möchten keine extends
Vererbung verwenden, da Sie möglicherweise bereits in Ihrer Klasse von einer anderen Klasse erben. Wäre es nicht großartig, eine generische Möglichkeit zu haben, eine Klasse ohne großen Aufwand steckbar zu machen ? Hier ist wie:
<?php
////////////////////
// PART 1
////////////////////
class Plugin {
private $_RefObject;
private $_Class = '';
public function __construct(&$RefObject) {
$this->_Class = get_class(&$RefObject);
$this->_RefObject = $RefObject;
}
public function __set($sProperty,$mixed) {
$sPlugin = $this->_Class . '_' . $sProperty . '_setEvent';
if (is_callable($sPlugin)) {
$mixed = call_user_func_array($sPlugin, $mixed);
}
$this->_RefObject->$sProperty = $mixed;
}
public function __get($sProperty) {
$asItems = (array) $this->_RefObject;
$mixed = $asItems[$sProperty];
$sPlugin = $this->_Class . '_' . $sProperty . '_getEvent';
if (is_callable($sPlugin)) {
$mixed = call_user_func_array($sPlugin, $mixed);
}
return $mixed;
}
public function __call($sMethod,$mixed) {
$sPlugin = $this->_Class . '_' . $sMethod . '_beforeEvent';
if (is_callable($sPlugin)) {
$mixed = call_user_func_array($sPlugin, $mixed);
}
if ($mixed != 'BLOCK_EVENT') {
call_user_func_array(array(&$this->_RefObject, $sMethod), $mixed);
$sPlugin = $this->_Class . '_' . $sMethod . '_afterEvent';
if (is_callable($sPlugin)) {
call_user_func_array($sPlugin, $mixed);
}
}
}
} //end class Plugin
class Pluggable extends Plugin {
} //end class Pluggable
////////////////////
// PART 2
////////////////////
class Dog {
public $Name = '';
public function bark(&$sHow) {
echo "$sHow<br />\n";
}
public function sayName() {
echo "<br />\nMy Name is: " . $this->Name . "<br />\n";
}
} //end class Dog
$Dog = new Dog();
////////////////////
// PART 3
////////////////////
$PDog = new Pluggable($Dog);
function Dog_bark_beforeEvent(&$mixed) {
$mixed = 'Woof'; // Override saying 'meow' with 'Woof'
//$mixed = 'BLOCK_EVENT'; // if you want to block the event
return $mixed;
}
function Dog_bark_afterEvent(&$mixed) {
echo $mixed; // show the override
}
function Dog_Name_setEvent(&$mixed) {
$mixed = 'Coco'; // override 'Fido' with 'Coco'
return $mixed;
}
function Dog_Name_getEvent(&$mixed) {
$mixed = 'Different'; // override 'Coco' with 'Different'
return $mixed;
}
////////////////////
// PART 4
////////////////////
$PDog->Name = 'Fido';
$PDog->Bark('meow');
$PDog->SayName();
echo 'My New Name is: ' . $PDog->Name;
In Teil 1 können Sie dies mit einem require_once()
Aufruf oben in Ihrem PHP-Skript einschließen . Es lädt die Klassen, um etwas steckbar zu machen.
In Teil 2 laden wir dort eine Klasse. Hinweis: Ich musste nichts Besonderes für die Klasse tun, was sich erheblich vom Observer-Muster unterscheidet.
In Teil 3 schalten wir unsere Klasse in "steckbar" um (dh unterstützt Plugins, mit denen wir Klassenmethoden und -eigenschaften überschreiben können). Wenn Sie beispielsweise eine Web-App haben, verfügen Sie möglicherweise über eine Plugin-Registrierung und können hier Plugins aktivieren. Beachten Sie auch die Dog_bark_beforeEvent()
Funktion. Wenn ich $mixed = 'BLOCK_EVENT'
vor der return-Anweisung setze , blockiert dies das Bellen des Hundes und blockiert auch das Dog_bark_afterEvent, da es kein Ereignis geben würde.
In Teil 4 ist dies der normale Betriebscode. Beachten Sie jedoch, dass das, was Sie vielleicht für möglich halten, überhaupt nicht so ausgeführt wird. Zum Beispiel gibt der Hund seinen Namen nicht als "Fido" bekannt, sondern als "Coco". Der Hund sagt nicht "Miau", sondern "Woof". Und wenn Sie sich später den Namen des Hundes ansehen möchten, stellen Sie fest, dass er "anders" anstelle von "Coco" ist. Alle diese Überschreibungen wurden in Teil 3 bereitgestellt.
Wie funktioniert das? Nun, lassen Sie uns ausschließen eval()
(was jeder als "böse" bezeichnet) und ausschließen, dass es sich nicht um ein Beobachtermuster handelt. Die Art und Weise, wie es funktioniert, ist die hinterhältige leere Klasse namens Pluggable, die nicht die von der Dog-Klasse verwendeten Methoden und Eigenschaften enthält. Da dies geschieht, werden sich die magischen Methoden für uns engagieren. Deshalb spielen wir in Teil 3 und 4 mit dem Objekt, das von der Pluggable-Klasse abgeleitet ist, und nicht mit der Dog-Klasse selbst. Stattdessen lassen wir die Plugin-Klasse das Dog-Objekt für uns "berühren". (Wenn das eine Art Designmuster ist, von dem ich nichts weiß - lassen Sie es mich bitte wissen.)