Take the following example, which although has basically the same methods as the SPL interfaces blended together require, it doesn't implement themthose interfaces at all. Instead, each method takes in a variable number of arguments (expected to be other SubjectObserver objects)...
abstract class SubjectObserver {
protected $observer_list = array();
public $status;
function update(SubjectObserver $subject) {
echo get_class($this) . " notified by " . get_class($subject) . ": " . $subject->status . "\n";
}
function __destruct() {
foreach ($this->observer_list as $observer)
$this->detach($observer);
}
function notify() {
$args = func_get_args();
foreach ($args as $arg)
$this->observer_list[get_class($arg)]->update($this);
}
function attach() {
$args = func_get_args();
foreach ($args as $arg) {
$this->observer_list[get_class($arg)] = $arg;
$this->status = "attaching " . get_class($arg);
$this->notify($arg);
}
}
function detach() {
$args = func_get_args();
foreach ($args as $arg) {
$this->status = "detaching " . get_class($arg);
$this->notify($arg);
unset($this->observer_list[get_class($arg)]);
}
}
}
class model extends SubjectObserver {}
class view extends SubjectObserver {}
class controller extends SubjectObserver {}
// initialize
$model = new model();
$view = new view();
$controller = new controller();
$model->attach($controller, $view);
$view->attach($controller, $model);
$controller->attach($model, $view);
// process some input
$controller->status = "input received";
$controller->notify($model);
$model->status = "data filtered";
$model->notify($controller, $view);