Created
November 6, 2020 12:51
-
-
Save stephanschuler/8ee13c017d7a141988474dc03b12885d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
/* | |
* Event Dispatcher and Emitter are separate objects | |
* ================================================= | |
* | |
* The dispatcher is meant to only receiver events: | |
* That's what the producing side holds. | |
* | |
* The emitter is meant for consumers to register. | |
* | |
* Variant: | |
* ======== | |
* | |
* Pro: | |
* ---- | |
* | |
* EventDispatcher::create() creates a EventDispatcher | |
* | |
* Con: | |
* ---- | |
* | |
* EventEmitter::__emit() is public but "internal" annotated | |
*/ | |
interface EventConsumer | |
{ | |
public function consume($data): void; | |
} | |
class EventDispatcher /* implements \Psr\EventDispatcher\EventDispatcherInterface */ | |
{ | |
private $emitter; | |
private function __construct(EventEmitter $emitter) | |
{ | |
$this->emitter = $emitter; | |
} | |
public static function create(): self | |
{ | |
$emitter = new EventEmitter(); | |
return new self($emitter); | |
} | |
public function dispatch($event): void | |
{ | |
$this->emitter->__emit($event); | |
} | |
public function getEmitter(): EventEmitter | |
{ | |
return $this->emitter; | |
} | |
} | |
class EventEmitter | |
{ | |
protected $consumers = []; | |
public function __construct() | |
{ | |
echo __METHOD__ . PHP_EOL; | |
} | |
public function __destruct() | |
{ | |
echo __METHOD__ . PHP_EOL; | |
} | |
public function register(EventConsumer $consumer): void | |
{ | |
$this->consumers[] = $consumer; | |
} | |
public function unregister(EventConsumer $consumer): void | |
{ | |
$this->consumers = array_filter($this->consumers, function (EventConsumer $delinquent) use ($consumer) { | |
return $delinquent === $consumer; | |
}); | |
} | |
/** @internal */ | |
public function __emit($event): void | |
{ | |
foreach ($this->consumers as $consumer) { | |
assert($consumer instanceof EventConsumer); | |
$consumer->consume($event); | |
} | |
} | |
} | |
echo 'Vorher' . PHP_EOL; | |
(function () { | |
$provider = EventDispatcher::create(); | |
$emitter = $provider->getEmitter(); | |
$emitter->register(new class implements EventConsumer { | |
public function consume($data): void | |
{ | |
echo 'erstes: ' . $data . PHP_EOL; | |
} | |
}); | |
$emitter->register(new class implements EventConsumer { | |
public function consume($data): void | |
{ | |
echo 'zweites: ' . $data . PHP_EOL; | |
} | |
}); | |
$provider->dispatch('xxx'); | |
$provider->dispatch('yyy'); | |
}) | |
(); | |
echo 'Nachher' . PHP_EOL; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
/* | |
* Event Dispatcher and Emitter are separate objects | |
* ================================================= | |
* | |
* The dispatcher is meant to only receiver events: | |
* That's what the producing side holds. | |
* | |
* The emitter is meant for consumers to register. | |
* | |
* Variant: | |
* ======== | |
* | |
* Pro: | |
* ---- | |
* | |
* EventEmitter has no publicly accessible method to put events in | |
* | |
* Con: | |
* ---- | |
* | |
* EventDispatcher::create() calls EventEmitter::createEventDispatcher() | |
* EventEmitter::createEventDispatcher() creates the EventDispatcher | |
* Clumsy anonymous function passed around | |
*/ | |
interface EventConsumer | |
{ | |
public function consume($data): void; | |
} | |
class EventDispatcher /* implements \Psr\EventDispatcher\EventDispatcherInterface */ | |
{ | |
private $emitter; | |
private $emitFunction; | |
public function __construct(EventEmitter $emitter, callable $emitFunction) | |
{ | |
$this->emitter = $emitter; | |
$this->emitFunction = $emitFunction; | |
} | |
public static function create(): self | |
{ | |
return EventEmitter::createEventDispatcher(); | |
} | |
public function dispatch($event): void | |
{ | |
($this->emitFunction)($event); | |
} | |
public function getEmitter(): EventEmitter | |
{ | |
return $this->emitter; | |
} | |
} | |
class EventEmitter | |
{ | |
protected $consumers = []; | |
public function __construct() | |
{ | |
echo __METHOD__ . PHP_EOL; | |
} | |
public static function createEventDispatcher(): EventDispatcher | |
{ | |
$emitter = new static(); | |
$emitFunction = function ($event) use (&$emitter): void { | |
assert($emitter instanceof EventEmitter); | |
$emitter->__emit($event); | |
}; | |
return new EventDispatcher($emitter, $emitFunction); | |
} | |
public function __destruct() | |
{ | |
echo __METHOD__ . PHP_EOL; | |
} | |
public function register(EventConsumer $consumer): void | |
{ | |
$this->consumers[] = $consumer; | |
} | |
public function unregister(EventConsumer $consumer): void | |
{ | |
$this->consumers = array_filter($this->consumers, function (EventConsumer $delinquent) use ($consumer) { | |
return $delinquent === $consumer; | |
}); | |
} | |
protected function __emit($event): void | |
{ | |
foreach ($this->consumers as $consumer) { | |
assert($consumer instanceof EventConsumer); | |
$consumer->consume($event); | |
} | |
} | |
} | |
echo 'Vorher' . PHP_EOL; | |
(function () { | |
$provider = EventDispatcher::create(); | |
$emitter = $provider->getEmitter(); | |
$emitter->register(new class implements EventConsumer { | |
public function consume($data): void | |
{ | |
echo 'erstes: ' . $data . PHP_EOL; | |
} | |
}); | |
$emitter->register(new class implements EventConsumer { | |
public function consume($data): void | |
{ | |
echo 'zweites: ' . $data . PHP_EOL; | |
} | |
}); | |
$provider->dispatch('xxx'); | |
$provider->dispatch('yyy'); | |
}) | |
(); | |
echo 'Nachher' . PHP_EOL; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment