Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I was trying to explain the mediator pattern to a new developer, and ended up writing a simple event mediator. Thoughts?

EventMediator

class EventMediator {
    private $events = array();

    public function attach($event, Closure $callback) {
        if(!is_string($event)) throw new \InvalidArgumentException();

        $event = strtolower(trim($event));
        if(!isset($this->events[$event])) $this->events[$event] = array();

        $this->events[$event][] = $callback;

        return $this;
    }

    public function trigger($event, $data = null) {
        if(!is_string($event)) throw new \InvalidArgumentException();

        $event = strtolower(trim($event));
        if(!isset($this->events[$event])) return false;

        foreach($this->events[$event] as $callback) $callback($event, $data);

        return true;
    }

    public function getEvents() { return $this->events; }
}

EventfulTrait

trait EventfulTrait {

    private $eventMediator;

    public function attachEventMediator(EventMediator $eventMediator) {
        $this->eventMediator = $eventMediator;
        return $this;
    }

    public function detachEventMediator() {
        $this->eventMediator = null;
        return $this;
    }

    public function getEventMediator() {
        return $this->eventMediator;
    }

    public function attachEvent($name, $callback) {
        if(!is_null($this->eventMediator)) $this->eventMediator->attach($name, $callback);
        return $this;
    }

    public function triggerEvent($name, $data = null) {
        if(!is_null($this->eventMediator)) return $this->eventMediator->trigger($name, $data);
        return false;
    }
}

Example

require "EventMediator.php";
require "EventfulTrait.php";

class Log {
    public function write($message) {
        echo "{$message}\n";
    }
}

class Eventful {
    use EventfulTrait;

    private $log;

    public function __construct() { $this->log = new Log(); }

    public function attachLoadEvent() {
        $self = $this;
        $log  = $this->log;
        $this->attachEvent(
            "load", function() use($self, $log) {
                $self->runOutOfNames();
                $log->write("log message");
            }
        );
    }

    public function doSomething() {
        $this->triggerEvent("load");
        $this->triggerEvent("event1");
    }

    public function doSomethingElse() {
        $this->triggerEvent("load");
        $this->triggerEvent("event1");
        $this->triggerEvent("event2");
    }

    public function runOutOfNames() { echo "load\n"; }
}

$eventMediator = new EventMediator();
$eventMediator->attach("event1", function() { echo "event1\n"; });
$eventMediator->attach("event2", function() { echo "event2\n"; });
$eventMediator->attach("done", function() { echo "done\n"; });

$eventful = new Eventful();
$eventful->attachEventMediator($eventMediator);
$eventful->attachLoadEvent();
$eventful->doSomething();
$eventful->doSomethingElse();

$eventMediator->trigger("load");
$eventMediator->trigger("done");

This will echo:

load
log message
event1
load
log message
event1
event2
load
log message
done
share|improve this question
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.