文档章节

要学好Yii的事件,先学学观察者模式

阿北2017
 阿北2017
发布于 2017/05/18 00:34
字数 1499
阅读 798
收藏 26
点赞 4
评论 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();

其实,在系统小的时候,这是非常快捷有效的方式。

但是,当系统变大的时候,这种方法马上面临难以扩展的问题,并且容易出错。

  • 比如老王不想订阅了,我们需要改源代码。
  • 比如又增加了一个客户,我们要去改源代码。
  • 比如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的事件,请大家对照着观察者模式,自己体会。

© 著作权归作者所有

共有 人打赏支持
阿北2017
粉丝 61
博文 54
码字总数 68986
作品 0
洛阳
加载中

评论(6)

happy_way
happy_way
好厉害
__FresHmaN
__FresHmaN

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

引用来自“__FresHmaN”的评论

北哥 v5

回复@__FresHmaN : 你认识我?是我小站会员么?
我认识Yii2
阿北2017
阿北2017

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

域名很精辟,是“我是奶爸”的意思么?:smile:

回复@无糖咖啡 : 哈哈,很聪明。
开元酒店警察
开元酒店警察
域名很精辟,是“我是奶爸”的意思么?:smile:
阿北2017
阿北2017

引用来自“__FresHmaN”的评论

北哥 v5

回复@__FresHmaN : 你认识我?是我小站会员么?
__FresHmaN
__FresHmaN
北哥 v5
JavaScript设计模式之观察者模式

前言 准备研究一下MVVM的一些东西,由于MVVM运用了观察者模式的思想,因此翻开了《JavaScript设计模式与开发实践》一书,将观察者模式学习了一遍,顺便有对一些常用的设计模式进行一些了解,...

Srtian ⋅ 05/22 ⋅ 0

代理模式(Proxy Pattern):动态代理 - 最易懂的设计模式解析

前言 今天我来全面总结开发中最常用的设计模式 - 代理模式中的动态代理模式 其他设计模式介绍 1分钟全面了解“设计模式” 单例模式(Singleton) - 最易懂的设计模式解析 简单工厂模式(Sim...

Carson_Ho ⋅ 04/09 ⋅ 0

系统架构技能之设计模式-单件模式

一、开篇 其实我本来不是打算把系统架构中的一些设计模式单独抽出来讲解的,因为很多的好朋友也比较关注这方面的内容,所以我想通过我理解及平时项目中应用到的一 些常见的设计模式,拿出来给...

wbf961127 ⋅ 2017/11/12 ⋅ 0

Java经典设计模式-结构型模式-适配器模式(Adapter)

适配器模式 适配器模式主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。 适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的...

Idea ⋅ 01/20 ⋅ 0

C#设计模式(2)——简单工厂模式

一、引言   这个系列也是自己对设计模式的一些学习笔记,希望对一些初学设计模式的人有所帮助的,在上一个专题中介绍了单例模式,在这个专题中继续为大家介绍一个比较容易理解的模式——简单工...

技术小胖子 ⋅ 2017/11/08 ⋅ 0

设计模式.策略模式

策略模式跟抽象工厂非常相似,基本逻辑是根据需要实例化出需要用的类。不同的是策略模式需要调用者非常清晰的知道有哪些策略,各个策略的调用规则,而抽象工厂的话,需要知道有哪些类,找到调...

技术小胖子 ⋅ 2017/11/08 ⋅ 0

不好意思,观察者模式跟发布订阅模式就是不一样

一、前言 一天,小猪佩奇去了一家西餐厅,点了一份西冷牛扒,还叫了圣女果。后来服务员上了一碟番茄,佩奇小姐:这是你的「圣女果」。佩奇猪一眼就看出了猫腻:这tm是番茄,不是圣女果啊!于...

Wilton ⋅ 05/08 ⋅ 0

简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别

转载:原地址http://www.cnblogs.com/zhangchenliang/p/3700820.html 简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别 结合简单示例和UML图,讲解工厂模式简单原理。 一、引子 话说...

法斗斗 ⋅ 05/08 ⋅ 0

设计模式Java Design Pattern-工厂方法模式FactoryMethod

我的博客 一、 设计模式的分类 大体可以分为三类: 创建型模式(5个) 单例模式、原型模式、工厂方法模式、抽象工厂模式、建造者模式 结构性模式(7个) 适配器模式、装饰器模式、代理模式、...

勇敢写信 ⋅ 03/22 ⋅ 0

JavaScript 中常见设计模式整理

开发中,我们或多或少地接触了设计模式,但是很多时候不知道自己使用了哪种设计模式或者说该使用何种设计模式。本文意在梳理常见设计模式的特点,从而对它们有比较清晰的认知。 JavaScript 中...

牧云云 ⋅ 05/18 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

UI ,前端框架选型

Flat-UI

miaojiangmin ⋅ 8分钟前 ⋅ 0

Istio Service Mesh 教程

Istio Service Mesh 教程 作者 宋净超 | 5400字 | 阅读大约需要11分钟 | 归档于istio | 发表于 2018-05-22 标签 #Istio #教程,来自 https://servicemesher.github.io/blog/istio-service-m...

openthings ⋅ 13分钟前 ⋅ 0

scala swing

scala swing组件的库 https://github.com/scala/scala-swing scala swing的API文档 https://www.scala-lang.org/api/2.9.1/scala/swing/package.html...

whoisliang ⋅ 17分钟前 ⋅ 0

CentOS安装配置Nginx

安装依赖 yum install gcc yum install pcre-devel yum install zlib zlib-devel yum install openssl openssl-devel //一键安装上面四个依赖 yum -y install gcc zlib zlib-devel pcre-deve......

临江仙卜算子 ⋅ 24分钟前 ⋅ 0

开源 java CMS - FreeCMS2.8 依申请公开

项目地址:http://www.freeteam.cn/ 依申请公开 1. 转交申请公开 用户可以把申请公开转交给其他人办理,系统会记录此申请公开的转交记录。 注意:同时只能转交一个申请公开。 选择需要转交的...

freeteam ⋅ 28分钟前 ⋅ 0

以太坊 web3.py 签名转账

以太坊 web3.py 签名转账 本文节选自电子书《Netkiller Blockchain 手札》 Netkiller Blockchain 手札 Mr. Neo Chan, 陈景峯(BG7NYT) 中国广东省深圳市龙华新区民治街道溪山美地 518131 +86...

netkiller- ⋅ 33分钟前 ⋅ 0

年薪40W的程序员必会的技术有哪些?

很多人在问我,程序员如何拿高薪,如何做到年薪40W+,其实总结出来还是一句话,你的技术决定你的能力已经薪资。 那么什么样的技术人才才能拿到一份Java行业里面的高薪呢? 下面是我的一个总结...

码代码的小司机 ⋅ 34分钟前 ⋅ 0

jesque-spring使用及源码分析

1.使用 jesque结合spring使用,步骤如下: 1.1 在项目中添加maven依赖 <dependency> <groupId>net.lariverosc</groupId> <artifactId>jesque-spring</artifactId> <version>1.0.0</ve......

Funcy1122 ⋅ 35分钟前 ⋅ 0

OSChina 周二乱弹 —— 加班的代码不要枉费了我的童子功

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @小小编辑:推荐歌曲《29》- 未完成乐队 《29》- 未完成乐队 手机党少年们想听歌,请使劲儿戳(这里) @FalconChen :#看球提醒# 02:00 巴西v...

小小编辑 ⋅ 今天 ⋅ 16

Docker Swarm的前世今生

概述 在我的《Docker Swarm集群初探》一文中,我们实际体验了Docker Swarm容器集群技术的魅力,与《Kubernetes实践录》一文中提到的Kubernetes集群技术相比,Docker Swarm没有Kubernetes显得...

CodeSheep ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部