php yii2 观察者模式,PHP观察者模式与Yii2.0事件

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
';

$this->trigger();

}

}

//观察者实现接口

class Observer1 implements ObserverInterface

{

public function update()

{

echo 'observer 1 update
';

}

}

class Observer2 implements ObserverInterface

{

public function update()

{

echo 'observer 2 update
';

}

}

$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 '
';

}

}

//短信 负责发送短信(相当于一个观察者)

class ShortMessage

{

public fucntion send($data)

{

echo 'short message send '.$data;

echo '
';

}

}

//评论类 必须继承自Components

class Comment extends Components

{

const EVENT_SEND_MESSAGE = 'send';

//保存成功触发发送通知消息事件

public function save()

{

echo 'comment save success';

echo '
';

$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的属性

学习yii2.0——事件

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

Yii2之事件

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

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

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

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

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

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

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

yii2.0 干货

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

Yii2.0 Cookies机制和使用方法

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

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

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

yii2.0归档安装方法

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

随机推荐

Effective C++ -----条款48:认识template元编程

Template metaprogramming(TMP,模板元编程)可将工作由运行期移往编译期,因而得以实现早期错误侦测和更高的执行效率. TMP可被用来生成“基于政策选择组合”(based on ...

关于MySQL建表

规范一些常用字段. password:varchar name:varchar 时间存储全部存储时间戳,用bigint(20),拒绝使用 MySQL数据类型  mysql数据类型 含义 date 3字 ...

[转]“WARNING: soft rlimits too low” in MongoDB with Mac OS X

转自:Programming and Technology If you get this warning when you connect to mongo shell in Mac OX X: * ...

awk 查找文件长度 删除

#在某个目录下,由于有些是缓存文件,它们的共同点就是长度大于3, 找到它们,然后用rm 命令删除#ls abc.pyabcd.py.... #ls | awk 'length($1) > 3 { ...

android推送-PHP(第三方推送:个推)

在项目初期,就安卓推送功能怎么做,曾经参考过例如XMPP之类的推送方法.但苦于那些是些英文档案,又没太多时间研究,所以打算采用第三方推送(个推,极光推送等),后来在美图技术老大推荐下用采用个推. PS ...

【hihoCoder 1466】后缀自动机六·重复旋律9

http://hihocoder.com/problemset/problem/1466 建出A串和B串的两个后缀自动机 对后缀自动机的每个状态求出sg值. 求出B串的\(sum(x)\),表示B有多 ...

iOS数据本地化

本篇随笔除了介绍 iOS 数据持久化知识之外,还贯穿了以下内容: (1)自定义 TableView,结合 block 从 ViewController 中分离出 View,轻 ViewControll ...

.NET ThreadPool算法

.NET ThreadPool相关算法记录 1.ManagedThreadPool (corefx) .net4.0之前只有全局队列,为了解决全局队列多线程竞争使用问题,引入work-stealing ...

React-Native视频组件react-native-video使用(安卓版)

你可能感兴趣的:(php,yii2,观察者模式)