Laravel框架的中间件使用:从请求进来到响应返回,经过中间件的层层包装,这种场景很适合用到一种设计模式---装饰器模式。

  装饰器模式的作用,多种外界因素改变对象的行为。使用继承的方式改变行为不太被建议。

  装饰器模式,即是有多个要改变对象的东西(装饰类),这些装饰类均实现一个接口。每个类在实现的接口中再调用构造器(或是setter等方法)传过来的其他装饰类对象的实现。

  简单用一段代码描述下:  

<?php

interface Decorate {
function getInfo();
} /**
* Class DecoateA
* 初始化一个装饰对象
*/
class DecoateA implements Decorate{ /**
* 实现接口
*/
public function getInfo() {
echo __CLASS__;
}
} /**
* Class DecoateB
* 装饰DecoateA 的装饰类
*/
class DecoateB implements Decorate{ /**
* DecoateB constructor.
* @param Decorate $dec
* 构造器 传过来其他装饰类
*/
public function __construct(Decorate $dec) {
$this->dec = $dec;
} /**
* 实现接口
*/
public function getInfo() {
echo __CLASS__;
$this->dec->getInfo();
}
} $obj = new DecoateA();// 初始一个对象
$obj = new DecoateB($obj);// 装饰对象 $obj->getInfo();// DecoateBDecoateA

以上代码,可以简单理解装饰器模式。

再说Laravel的装饰器模式应用: (这里用静态方法模拟一下)

不像是上边的例子,把装饰类传过去,Laravel用到了大量的闭包Closure代替

一段代码

<?php

interface Step
{
public static function go(Closure $next);
} /**
* Class FirstStep
* 装饰一
*/
class FirstStep implements Step
{
public static function go(Closure $next)
{
echo __CLASS__." start<br/>";
$next();
echo __CLASS__." end<br/>";
}
} /**
* Class SecondStep
* 装饰二
*/
class SecondStep implements Step
{
public static function go(Closure $next)
{
echo __CLASS__." start<br/>";
$next();
echo __CLASS__." end<br/>";
}
} function goFun($step, $className)
{
return function () use ($step, $className)
{
return $className::go($step);
};
} function then()
{
$step = ['FirstStep', 'SecondStep'];
$prepare = function () {
echo "_init_"."<br/>";
};
call_user_func(array_reduce($step, "goFun", $prepare));
} then(); /**
SecondStep start
FirstStep start
_init_
FirstStep end
SecondStep end
**/

这里需要理解下 array_reduct()的用法,第一个参数是被循环的数组,第二个是回调函数(其中回调函数的第一个参数是每次该函数上一次的return值,否则是array_reduce的第三个参数的初始值),第三个参数是初始值。

对于then() 的内部实现,可能开始理解比较困难。可以分拆一下实现:如下代码

// 初始闭包
$initFun = function (){
echo "_init_"."<br/>";
}; // 相当于array_reduce 第一次执行
$obj = function () use ($initFun) {
return FirstStep::go($initFun);
}; // 相当于array_reduce 第二次执行。go传递的都是个闭包函数
SecondStep::go($obj);

装饰器模式以及Laravel框架下的中间件应用的更多相关文章

  1. 装饰器模式(Decorator)——深入理解与实战应用

    本文为原创博文,转载请注明出处,侵权必究! 1.初识装饰器模式 装饰器模式,顾名思义,就是对已经存在的某些类进行装饰,以此来扩展一些功能.其结构图如下: Component为统一接口,也是装饰类和被装 ...

  2. 深入探索Java设计模式(三)之装饰器模式

    装饰器模式使你可以在运行时使用类似于对象组成的技术来装饰类.这在我们希望实例化具有新职责的对象而无需对基础类进行任何代码更改的情况下尤其有用.本文是在学习完优锐课JAVA架构VIP课程—[框架源码专题 ...

  3. 从ES6重新认识JavaScript设计模式: 装饰器模式

    1 什么是装饰器模式 向一个现有的对象添加新的功能,同时又不改变其结构的设计模式被称为装饰器模式(Decorator Pattern),它是作为现有的类的一个包装(Wrapper). 可以将装饰器理解 ...

  4. ReplayingDecoder 解码器:别以为我有多厉害,也只不过是使用了一下装饰器模式而已~

    原文地址 一.设计模式为啥老是用不好? 想要写出更屌的代码,提高代码的健壮性和可扩展性,那么设计模式可谓是必学的技能. 关于学习设计模式,大家可能都觉得设计模式的概念太过于抽象,理解起来有点费劲:又或 ...

  5. PHP 装饰器模式

    装饰器模式:是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能. [装饰器模式中主要角色] 抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,即可以给这 ...

  6. 设计模式-装饰器模式(Decrator Model)

    文 / vincentzh 原文连接:http://www.cnblogs.com/vincentzh/p/6057666.html 目录 1.概述 2.目的 3.结构组成 4.实现 5.总结 1.概 ...

  7. Java设计模式12:装饰器模式

    装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...

  8. 说说设计模式~装饰器模式(Decorator)~多功能消息组件的实现

    返回目录 为何要设计多功能消息组件 之前写过一篇装饰器模式的文章,感觉不够深入,这次的例子是实现项目中遇到的,所以把它拿出来,再写写,之前也写过消息组件的文章,主要采用了策略模式实现的,即每个项目可以 ...

  9. (十)装饰器模式详解(与IO不解的情缘)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. LZ到目前已经写了九个设计模 ...

随机推荐

  1. 浅谈RNN、LSTM + Kreas实现及应用

    本文主要针对RNN与LSTM的结构及其原理进行详细的介绍,了解什么是RNN,RNN的1对N.N对1的结构,什么是LSTM,以及LSTM中的三门(input.ouput.forget),后续将利用深度学 ...

  2. javascript基础修炼(11)——DOM-DIFF的实现

    目录 一. 再谈从Virtual-Dom生成真实DOM 二. DOM-Diff的目的 三. DOM-Diff的基本算法描述 四. DOM-Diff的简单实现 4.1 期望效果 4.2 DOM-Diff ...

  3. Docker在Linux/Windows上运行NetCore文章系列

    Windows系列 因为Window很简单,VS提供界面化配置,所以只写了一篇文章 Docker在Windows上运行NetCore系列(一)使用命令控制台运行.NetCore控制台应用 Linux( ...

  4. CSS引用样式

    llink和@import引入外部样式的区别 •隶属上的差别 link属于HTML标签,而@import完全是CSS提供的一种方式. •@import次数限制 @import只能引入31次css文件. ...

  5. JSON 数据转换

    JSON概述      JSON(Java Script Object Notation)JS对象符号,通常JSON和XML是二选一的,JSON的数据格式很类似于JavaScript的对象 { &qu ...

  6. Apollo配置中心源码分析

    Apollo配置中心源码分析 1. apollo的核心代码分享 SpringApplication启动的关键步骤 在SpringApplication中,会加载所有实现了Init方法的类 protec ...

  7. 读书笔记--《Effective C#》总结

    值得推荐的一本书,适合初中级C#开发人员 第1章 C#语言元素 原则1:尽可能的使用属性(property),而不是数据成员(field) ● 属性(property)一直是C#语言中比较有特点的存在 ...

  8. 原生JS编写兼容IE6,7,8浏览器无缝自动轮播(带按钮切换)

    项目要求页面兼容IE6,7,8等浏览器,我们可能会遇到这个轮播效果,轮播板块要求:无限循环.自动轮播和手动切换功能,每一次滚动一小格,网上有很多这类插件,例如:swiper等! 但是很多都是不兼容IE ...

  9. html中节点类型

    常用的节点有元素节点.属性节点.文本节点.注释节点.文档节点 来看例子: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transition ...

  10. HTML中特殊符号