一、先看PHP观察者模式的实现:html
//事件的基类 abstract class BaseEvent { private static $observer; //添加观察者 public function addObserver($obj) { self::$observer[] = $obj; } //触发事件、通知全部的观察者 public function trigger() { foreach(self::$observer as $observer){ $observer->update(); } } } //做为观察者要实现的接口 interface ObserverInterface { public function update(); } //具体的一个事件类、要继承事件基类 class Event extends BaseEvent { public function test() { //执行事件 echo 'test execute success. notify observer <br />'; $this->trigger(); } } //观察者实现接口 class Observer1 implements ObserverInterface { public function update() { echo 'observer 1 update<br />'; } } class Observer2 implements ObserverInterface { public function update() { echo 'observer 2 update<br />'; } } $e = new Event(); //添加两个观察者 $o1 = new Observer1(); $o2 = new Observer2(); $e->addObserver($o1); $e->addObserver($o2); $e->test(); //输出 //test execute success. notify observer //observer 1 update //observer 2 update
这种实现方式的好处是:数组
很差的地方在于:框架
二、看Yii2.0中event的实现方式this
精简版:code
//全部想要使用事件功能的类都要继承 class Components { //保存全部的时间 private $_events = []; //绑定事件 public function on($eventName, $handler, $data) { $this->_events[$eventName][] = [$handler, $data]; } //触发事件 public function trigger($eventName, $event=null) { foreach($this->_events[$eventName] as $handler){ call_user_func($handler[0], $handler[1]); } } } //邮件类 负责发送邮件(至关于一个观察者) class Email { public function send($data) { echo 'email send '.$data; echo '<br />'; } } //短信 负责发送短信(至关于一个观察者) class ShortMessage { public fucntion send($data) { echo 'short message send '.$data; echo '<br />'; } } //评论类 必须继承自Components class Comment extends Components { const EVENT_SEND_MESSAGE = 'send'; //保存成功触发发送通知消息事件 public function save() { echo 'comment save success'; echo '<br />'; $this->trigger(self::EVENT_SEND_MESSAGE); } } $comment = new Comment(); $emailHandler = [new Email(), 'send']; $smsHandler = [new ShortMessage(), 'send']; //注册两个事件 $comment->on(Comment::EVENT_SEND_MESSAGE, $emailHandler, 'for comment.'); $comment->on(Comment::EVENT_SEND_MESSAGE, $smsHandler, 'for comment.'); //保存评论 $comment->save(); //输出 comment save success email send for comment. short message send for comment.
对比第一种观察者模式的实现:server
改进:改进trigger方法htm
//添加Event类 class Event { public $data = null; } //修改trigger方法 public function trigger($eventName, $event=null) { if(is_null($event)){ $event = new Event(); } foreach($this->_events[$eventName] as $handler){ $event->data = $handler[1]; call_user_func($handler[0], $event); } }
修改以后传递给事件 处理者。定义统一的一个event以后,全部的事件处理者须要继承此类,call_user_func传递的再也不是data了,而是一个event对象对象
因此Yii框架事件两种传递数据的方式:blog
最终trigger传递的事实上是一个event,on传递的参数变成了event的data的属性继承