深入 Laravel 内核之观察者模式
装饰模式核心内容:
- 观察者模式又称为发布订阅模式,定义了对象间的一对多依赖关系,当一个对象状态发生改变时,其相关依赖的其他对象都能接收到通知;
- 观察者模式的核心在于目标(Subject)和观察者(Observer)接口,目标有一个状态属性,观察者“订阅”这个目标,当目标的状态属性发生改变时,通知所有观察者。
- 目标状态改变只需核心业务逻辑并调用通知接口,无需关心具体的观察者及其数量,降低对象之间的耦合度;
定义一个目标抽象类,提供绑定&解绑观察者的接口供客户端使用,提供通知观察者的接口供目标实现类使用:
abstract class Subject
{
protected $stateNow;
protected $observers = [];
public function attach(Observer $observer)
{
echo __CLASS__ . "绑定观察者:" . $observer->getClassName() . "\n\r";
array_push($this->observers, $observer);
}
public function detach(Observer $observer)
{
$pos = 0;
foreach ($this->observers as $viewer) {
if ($viewer == $observer) {
array_splice($this->observers, $pos, 1);
}
$pos++;
}
}
public function notify()
{
foreach ($this->observers as $viewer) {
echo __CLASS__ . "通知观察者:" . $viewer->getClassName() . "\n\r";
$viewer->update($this);
}
}
}
定义一个目标实现类,实现状态的变更业务:
class ConcreteSubject extends Subject
{
public function setState($state)
{
echo __CLASS__ . "修改状态并调用 notify 方法\n\r";
$this->stateNow = $state;
$this->notify();
}
public function getState()
{
return $this->stateNow;
}
}
定义一个观察者抽象类,规范接收通知的接口:
abstract class Observer
{
abstract public function update(Subject $subject);
abstract public function getClassName();
}
定义两个观察者实现类,实现接收通知的业务逻辑:
class ConcreteObserverEmail extends Observer
{
//维护一个指向具体目标对象的引用
private $currentState;
public function update(Subject $subject)
{
$this->currentState = $subject->getState();
echo $this->getClassName() . "收到了通知,内容为:" . $this->currentState . "\n\r";
}
public function getClassName() {
return __CLASS__;
}
}
class ConcreteObserverPhone extends Observer
{
//维护一个指向具体目标对象的引用
private $currentState;
public function update(Subject $subject)
{
$this->currentState = $subject->getState();
echo $this->getClassName() . "收到了通知,内容为:" . $this->currentState . "\n\r";
}
public function getClassName() {
return __CLASS__;
}
}
定义一个客户端,给目标绑定观察者,查看效果:
class Client
{
public function main()
{
$sub = new ConcreteSubject();
$obEmail = new ConcreteObserverEmail();
$obPhone = new ConcreteObserverPhone();
$sub->attach($obEmail);
$sub->attach($obPhone);
$sub->setState('开启');
}
}
(new Client())->main();
输出结果:
Subject绑定观察者:ConcreteObserverEmail
Subject绑定观察者:ConcreteObserverPhone
ConcreteSubject修改状态并调用 notify 方法
Subject通知观察者:ConcreteObserverEmail
ConcreteObserverEmail收到了通知,内容为:开启
Subject通知观察者:ConcreteObserverPhone
ConcreteObserverPhone收到了通知,内容为:开启
深入 Laravel 内核之观察者模式的更多相关文章
- 深入 Laravel 内核之IOC容器
升级工厂前的准备工作 无规矩不成方圆,随着越来越多的行为出现,我们需要需要定下一些规范. 为了约束每一个行为的规范,需要定义一个行为接口: interface BehaviorInterface { ...
- 深入 Laravel 内核之工厂模式
英雄与行为,依赖的诞生 首先定义一个英雄,英雄具有一些行为: class Hero { protected $behavior = []; public function show() { var_d ...
- 深入 Laravel 内核之装饰模式
装饰模式核心内容: 装饰模式可以在不影响组件对象的情况下,以动态.透明的方式从外部给对象添加功能: 装饰器模式的本质就是动态组合.动态是手段,组合是目的.装饰模式是通过把复杂的功能简单化.分散化,在运 ...
- 深入 Laravel 内核之外观模式(门面模式)
门面模式核心内容: 客户端与子系统的通信通过外观对象进行: 外观对象封装一系列子系统的具体对应方法,对客户端只需暴露一个单一的入口方法: 客户端通过访问外观对象即可调用子系统的基础方法,无需关心子系统 ...
- 深入 Laravel 内核之 PHP 反射机制和依赖注入
结论: PHP中提供了反射类来解析类的结构: 通过反射类可以获取到类的构造函数及其参数和依赖: 给构造函数的参数递归设置默认值后,即可使用这些带默认值的参数通过 newInstanceArgs 实例化 ...
- laravel 实现思路以及各组件原理
laravel 内核是个IOC容器,IOC是把本来自己实例化的对象. 通过在容器里注册,通过容器来进行实例化. laravel队列用的是redis的列表来实现.
- Laravel 从入门到精通系列教程
转载;https://laravelacademy.org/laravel-tutorial-5_7 适用于 Laravel 5.5.5.6.5.7 版本,本系列教程将围绕一个 LTS 版本,然后采取 ...
- Laravel源码解析之从入口开始
前言 提升能力的方法并非使用更多工具,而是解刨自己所使用的工具.今天我们从Laravel启动的第一步开始讲起. 入口文件 laravel是单入口框架,所有请求必将经过index.php define( ...
- Laravel核心解读--Contracts契约
Contracts Laravel 的契约是一组定义框架提供的核心服务的接口, 例如我们在介绍用户认证的章节中到的用户看守器契约IllumninateContractsAuthGuard 和用户提供器 ...
随机推荐
- KVM配置
安装依赖包(因最小化安装) [root@slave-master ~]# yum install -y vim wget tree lrzsz gcc gcc-c++ automake pcre pc ...
- C#内建接口:IEnumerable
这节讲一下接口IEnumerable. 01 什么是Enumerable 在一些返回集合数据的接口中,我们经常能看到IEnumerable接口的身影.那什么是Enumerable呢?首先它跟C#中的e ...
- 试工具_ab
目录 一.简介 二.例子 三.参数 一.简介 ab命令会创建多个并发访问线程,模拟多个访问者同时对某一URL地址进行访问.它的测试目标是基于URL的. 1.ab每次只能测试一个URL,适合做重复压力测 ...
- 虚拟机+OS系统安装+Xshell
安装虚拟机 1.先下载好VMware Workstation.exe的安装包(最好直接下载破解版(非最新版) 在此私人网址不公布 可直接百度 资源很多) 2.直接下一步 直到安装完成(注意最好不要装在 ...
- BIT 常态化在线CTF系统 pwn题目
偶然得到这个平台,发现是BIT的CTF平台,应该是平时的阶段性的训练题目.看了看题,其他方向的题目感觉都是入门题,但是pwn题目,发现还是比入门题难一点点的,来记录一下. pwn1 栈上任意位置的读写 ...
- ctfshow 红包题 武穆遗书
偶然见看到这道题,就下载了看了看.确实是我自己的逆向能力不够,逆不动.但是我似乎找到了非预期... 下载程序,ida打开,发现不对.后来发现是加了upx壳,拿软件去一下.再次ida打开. 其中buff ...
- Table.CombineColumns合并…Combine…(Power Query 之 M 语言)
数据源: 任意表,表中列数超过两列 目标: 其中两列合并为一列 操作过程: 选取两列>[转换]>[合并列]>选取或输入分隔符>输入新列名>[确定] M公式: = T ...
- grep的时候Binary file matches **.log 怎么解决
操作 grep "hello world" test.log 结果 Binary file test.log matches 原因:grep认为test.log是二进制文件 解决方 ...
- java 编程基础 Class对象 反射:动态代理 和AOP:java.lang.reflect.Proxy:(Proxy.newProxyInstance(newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h))
为什么我们使用动态代理 静态代理会让类变多了,多了代理类,工作量变大了,且不易扩展.比如我们上节课的例子,要实现不同的扩展方法就要编写不同的代理类,非常麻烦. Proxy类的使用规则 Proxy提 ...
- Python第二周 str的方法
str.start #!/usr/bin/env python # Author:Zhangmingda while True: cmd = input('输入字符:')#.strip() print ...