Tell me more ×
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

Know someone who can answer? Share a link to this question via email, Google+, Twitter, or Facebook.

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.