1、先看PHP观察者模式的实现:

  • 想要使用事件、必须实现事件的基类、统一的addObserver和trigger方法
  • 定义统一接口、所有的观察者都要实现此接口
//事件的基类
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

这种实现方式的好处是:

  • 直接addObserver就好、事件完成之后直接触发就行了、因为观察者实现了统一的接口

不好的地方在于:

  • 每个观察者都要去实现接口
  • 如果触发的时候要传递数据、就只能修改接口中的定义、并且还要修改BaseEvent中的update方法

2、看Yii2.0中event的实现方式

精简版:

  • 只有事件绑定和触发
  • 只有对象级别的绑定和触发(没有类级别的)
//所有想要使用事件功能的类都要继承
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.

对比第一种观察者模式的实现:

  • 不需要每个观察者都实现统一的接口
  • 利用call_user_func可以之间传递数组:包括对象实例和对应的方法

改进:改进trigger方法

  • 触发时传递数据给观察者
//添加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框架事件两种传递数据的方式:

  • 在on绑定的时候
  • 在trigger的时候

最终trigger传递的事实上是一个event,on传递的参数变成了event的data的属性

原文链接:http://www.cnblogs.com/skyfynn/p/8891008.html

PHP观察者模式与Yii2.0事件的更多相关文章

  1. 学习yii2.0——事件

    参考:https://www.yiichina.com/doc/guide/2.0/concept-events 事件 yii框架中的事件定义和JavaScript中的事件定义差不多:为某个事件绑定一 ...

  2. Yii2之事件

    众所周知,yii的三大特性是:属性.事件.行为,上一篇博文简单讲解了yii中的属性,本文接着讲讲yii的事件. 事件是代码解耦的一种方式,设计业务流程的一种模式.在yii2.0中,通过Yii\base ...

  3. Yii2.0源码阅读-behavior的实现原理

    Yii2.0中的一个思想就是组件化的思想,所以.大多数的类都直接或间接的继承自yii\base\Component,而组件的三大功能:属性.事件.行为. 行为的目的是为了方便的扩展一个类的功能,而不需 ...

  4. Yii 2.x 和1.x区别以及yii2.0安装

    知乎上有个类似的问题:http://www.zhihu.com/question/22924271/answer/23085751 大致思路不会变,开发流程变化也不是很大.有变化的是1.yii2带入的 ...

  5. Yii2.0源码分析之——控制器文件分析(Controller.php)创建动作、执行动作

    在Yii中,当请求一个Url的时候,首先在application中获取request信息,然后由request通过urlManager解析出route,再在Module中根据route来创建contr ...

  6. yii2.0 干货

    Yii2 干货集,欢迎提交 Pull Requests.(提交过来的开源项目最好是你用过的,并且觉得好用的) Docs 文档 Yii Framework 2.0 类参考手册 Yii Framework ...

  7. Yii2.0 Cookies机制和使用方法

    在实际的项目开发过程中,用到了Yii2.0 Cookies机制!但是遇到一个十分奇葩的问题,同一个YII框架,backend下Cookies能够正常存储于客户端,但是frontend始终不行.文章的最 ...

  8. Yii2.0.7 限制user module登录遇到的问题

    在Yii2.0.6的时候我是在以下文件通过以下方法实现的. frontend/modules/user/Module.php namespace frontend\modules\user; clas ...

  9. yii2.0归档安装方法

    我前几天用composer安装 一直没成功  我就用归档的方法安装了  所以这篇文字只帮助那些用归档方法安装的朋友 Yii是一个高性能的,适用于开发WEB2.0应用的PHP框架. Yii自带了丰富的功 ...

随机推荐

  1. 记录python接口自动化测试--unittest框架基本应用(第二目)

    在第一目里写了几个简单demo,并把调用get和post请求的方法封装到了一个类里,这次结合python自带的unittest框架,用之前封装的方法来写一个接口测试demo 1.unittest简单用 ...

  2. TED - How To Get Better At The Things You Care About

    TED01 - How To Get Better At The Things You Care About 昨天我发布了攻克英语口语的宣言,今天就行动.TED是我们学习口语的好地方,本着学以致用的原 ...

  3. C语言博客作业—结构体

    一.PTA实验作业 题目1:结构体数组按总分排序 1. 本题PTA提交列表 2. 设计思路 void calc //函数calc求出p指针所指的结构体数组中 n 名学生各自的总分 { 定义循环变量i: ...

  4. Beta开始前准备

    Beta准备 1. 讨论组长是否重选的议题和结论. 经过讨论,我们认为,经过一段时间的磨合,现任组长是不需要更换的. 2. 下一阶段需要改进完善的功能. 增加关于征信的功能,贴近选题主题 美化界面,尽 ...

  5. Swift -欢迎界面1页, 延长启动图片的显示时间(LaunchImage)

    转自:http://www.hangge.com/blog/cache/detail_1238.html http://www.hangge.com/blog/cache/detail_672.htm ...

  6. Flask 扩展 缓存

    如果同一个请求会被多次调用,每次调用都会消耗很多资源,并且每次返回的内容都相同,就该使用缓存了 自定义缓存装饰器 在使用Flask-Cache扩展实现缓存功能之前,我们先来自己写个视图缓存装饰器,方便 ...

  7. 【基础知识】Flex-弹性布局原来如此简单!!

    简言 布局的传统解决方案是基于盒状模型,依赖 display + position + float 方式来实现,灵活性较差.2009年,W3C提出了一种新的方案-Flex,Flex是Flexible ...

  8. react基础篇入门组件

    讲述一下React: 1.声明式设计-React采用声明范式,可以轻松描述应用 2.高效-React通过DOM模型,最大限度的减少dom的交互 3.灵活-React可以与已知的库或框架很好的配合 4. ...

  9. PV & PVC - 每天5分钟玩转 Docker 容器技术(150)

    Volume 提供了非常好的数据持久化方案,不过在可管理性上还有不足. 拿前面 AWS EBS 的例子来说,要使用 Volume,Pod 必须事先知道如下信息: 当前 Volume 来自 AWS EB ...

  10. tcltk控制chariot进行测试 couldn't load library "ChariotExt": invalid argument

    解决办法:和tcl版本有关,我的chariot应该是32位的,下载win32-ix86的tcl解决了,用64位的有这个错误提示. ActiveTcl8.6.4.1.299124-win32-ix86- ...