PHP 使用闭包实现观察者模式
示例
通常,观察者是一类,当对被观察对象执行操作时,将调用特定方法。在某些情况下,闭包足以实现观察者设计模式。
这是这种实现的详细示例。首先声明一个类,其目的是在属性更改时通知观察者。
<?php class ObservedStuff implements SplSubject { protected $property; protected $observers = []; public function attach(SplObserver $observer) { $this->observers[] = $observer; return $this; } public function detach(SplObserver $observer) { if (false !== $key = array_search($observer, $this->observers, true)) { unset($this->observers[$key]); } } public function notify() { foreach ($this->observers as $observer) { $observer->update($this); } } public function getProperty() { return $this->property; } public function setProperty($property) { $this->property = $property; $this->notify(); } }
然后,让我们声明将代表不同观察者的类。
<?php class NamedObserver implements SplObserver { protected $name; protected $closure; public function __construct(Closure $closure, $name) { $this->closure = $closure->bindTo($this, $this); $this->name = $name; } public function update(SplSubject $subject) { $closure = $this->closure; $closure($subject); } }
让我们最后测试一下:
<?php $o = new ObservedStuff; $observer1 = function(SplSubject $subject) { echo $this->name, ' has been notified! New property value: ', $subject->getProperty(), "\n"; }; $observer2 = function(SplSubject $subject) { echo $this->name, ' has been notified! New property value: ', $subject->getProperty(), "\n"; }; $o->attach(new NamedObserver($observer1, 'Observer1')) ->attach(new NamedObserver($observer2, 'Observer2')); $o->setProperty('Hello world!'); //显示: //Observer1已收到通知!新物业价值:世界您好! //Observer2已收到通知!新物业价值:世界您好!
请注意,此示例之所以有效,是因为观察者具有相同的性质(他们都是“命名的观察者”)。