要学好Yii的事件,先学学观察者模式
要学好Yii的事件,先学学观察者模式
阿北2017 发表于5个月前
要学好Yii的事件,先学学观察者模式
  1. 发表于 5个月前
  2. 阅读 774
  3. 收藏 26
  4. 点赞 4
  5. 评论 6
腾讯云 十分钟定制你的第一个小程序>>>   
Yii2的事件采用了“观察者模式”,先了解观察者,再学事件就容易了。

它是什么

首先不要被名字所吓倒,往下看,它真的很简单。 先来一个比较高大上的定义:观察者模式定义了一系列对象之间的一对多关系,当一个对象改变状态后,其他依赖者都会收到通知。 看明白了么? 如果没明白我们再来一个生活一点的:观察者模式就是订报纸的模式,你和一些人向某个报社订报纸,只要有新报纸出版,报社就会给你们送来,具体你们怎么看和报社无关,只要报社不倒闭,就会一直给你们送。 当然,你也可以退订。 观察者模式 == 报社 + 订报纸的人 无论你明白了哪种定义,记住一点,“观察者模式”最牛逼的地方就是让一些彼此依赖的类松耦合,牛逼的系统是什么样的?那就是每个对象间的依赖程度降到冰点,但是依然可以交互。

一个活生生的例子

没例子的技术文都是流氓文,我给大家举个例子,让你更形象化的理解观察者模式。 所有的观察者模式中一定有一个主题和一堆观察者,比如北哥兄弟连和每一个订阅会员

对于主题(北哥兄弟连 nai8.me

每一天的某一刻兄弟连有了新视频,然后我会告诉所有的订阅者。 我仅仅是通知了所有订阅者有新视频了。

对于观察者(订阅者)

订阅者小明:收到后忽略通知 订阅者隔壁老王:立刻开始看视频 订阅者川普:收藏了一下,然后去wc看 订阅者冰冰:立刻开始看视频 等等等等 日复一日,年复一年,主题并不清楚订阅者收到通知后都干嘛了啥,它也不关心,主题的责任就是告诉他们。 对于观察者,就像一个清单,清单中的每个人都会收到新课通知,然后自己进行自己的处理。 突然有一天 订阅者隔壁老王说:“老子不学了,不要再告诉我”。 于是,老王从清单被清除,它不再是观察者,主题也不会给它再发。

Code it

我想到此刻,你已经清楚了观察者模式,但是作为一个语言类文章,不写点代码总说不过去,我们接下来用代码来实现上面的需求。 我们先来一个不用观察者模式的代码 class Video { public function new(){ $checkNewVideo = Video::find()->where("xxxxx")->one(); if($checkNewVideo){ // 通知各位 LaoWang::newVideo(); XiaoLi::newVideo(); ChuanPu::newVideo(); ....... // 还有很多很多,比如在给某个集体客户群发、短信发等等等等 } } } // 具体实现 $model = new Video(); $model->new(); 其实,在系统小的时候,这是非常快捷有效的方式。 但是,当系统变大的时候,这种方法马上面临难以扩展的问题,并且容易出错。
  1. 比如老王不想订阅了,我们需要改源代码。
  2. 比如又增加了一个客户,我们要去改源代码。
  3. 比如xxx,我们都需要改源代码。
这两个对象的耦合度太高了。

解决它 - 用观察者模式

我们先改进上面的代码 /** * 被观察者接口 * 定义了一些公用方法声明,使用观察者模式的类都可以继承此接口 */ interface Observable { // 添加/注册观察者 public function attach(Observer $observer); // 删除观察者 public function detach(Observer $observer); // 触发通知 public function notify(); } class Video implements Observable { public $observers = [];// 订阅者 // 添加观察者 public function attach(Observer $observer){ $key = array_search($observer, $this->observers); if ($key === false) { $this->observers[] = $observer; } } // 删除观察者 public function detach(Observer $observer){ $key = array_search($observer, $this->observers); if ($key !== false) { unset($this->observers[$key]); } } // 通知所有观察者 public function notify(){ foreach ($this->observers as $observer) { // 把本类对象传给观察者 $observer->update($this); } } public function new(){ $checkNewVideo = Video::find()->where("xxxxx")->one(); if($checkNewVideo){ $this->notify(); } } } 你看到了,修改后的代码并不关心具体发送给谁,它只是遍历了所有观察者的列表,然后告诉他们一下而已,观察者增减对此类不会有任何影响。 对于观察者,数字不定,随时有增减,因此我们定义了一个观察者接口开始抽象它们。 /** * 观察者接口 */ interface Observer { // 接收到通知的处理方法 public function update(Observable $observable); } 老王、小明、川普、冰冰订阅了视频 class LaoWang implements Observer { public function update(Observable $observable){ echo "立刻开始看视频"; } } class XiaoMing implements Observer { public function update(Observable $observable){ echo "收到后忽略通知"; } } class ChuanPu implements Observer { public function update(Observable $observable){ echo "收藏了一下,然后去wc看"; } } class BingBing implements Observer { public function update(Observable $observable){ echo "立刻开始看视频"; } } 具体实现 $model = new Video(); $model->attach(new LaoWang()); $model->attach(new XiaoLi()); $model->attach(new ChuanPu()); $model->attach(new BingBing()); $model->new(); 这样当我们再增加一个人加入 习大大 的时候,我们只需要增加一个习大大的观察者类,在实现的时候添加注册,而不需要去改Video类和其他的观察者类,将类之间的耦合降低了很多。

回头看

上面就是观察者模式,我们先预想一下我们的事件,假设我们定义了很多观察者代码,他们监听事件的发生,当一个事件被触发,这些观察者都会知道,执行各自的逻辑。 事件就是观察者模式的一种应用。 监听系统的某一个行为,实时获取并执行自己负责的代码。 如果你看懂了上面的,恭喜你事件已经入门一半,下一篇开始说Yii的事件,请大家对照着观察者模式,自己体会。
标签: Yii2
  1. 打赏
  2. 点赞
  3. 收藏
  4. 分享
共有 人打赏支持
粉丝 54
博文 37
码字总数 40799
评论 (6)
__FresHmaN
北哥 v5
阿北2017

引用来自“__FresHmaN”的评论

北哥 v5
回复@__FresHmaN : 你认识我?是我小站会员么?
无糖咖啡
域名很精辟,是“我是奶爸”的意思么?:smile:
阿北2017

引用来自“无糖咖啡”的评论

域名很精辟,是“我是奶爸”的意思么?:smile:
回复@无糖咖啡 : 哈哈,很聪明。
__FresHmaN

引用来自“阿北2017”的评论

引用来自“__FresHmaN”的评论

北哥 v5
回复@__FresHmaN : 你认识我?是我小站会员么?
我认识Yii2
happy_way
好厉害
×
阿北2017
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额:
利发国际官方网