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. 解读经典《C#高级编程》第七版 Page94-100.继承.Chapter4

    前言 今天,我们开始进入第四章的解读.本章讲的是继承.要做稍微复杂一些的开发,便不可避免的会使用到继承.本篇文章我们主要解读"实现继承". 另外,从本文开始,我开始使用Markdo ...

  2. nginx基础

    常见的能够提供web服务的程序有apache.IIS,nginx等,LLS是windows系统中的,nginx和apache是linux系统中的,nginx是一款高性能的http和反向代理的服务器. ...

  3. DSAPI多功能组件编程应用-文件类

    [DSAPI.DLL下载地址]     本节内容,是属于"无需过多说明"就能使用的功能.由于实在是太简单,我就简单地示例一下. DSAPI.文件类.获取可读性强的字节大小信息(&q ...

  4. [转]在node.js中,使用基于ORM架构的Sequelize,操作mysql数据库之增删改查

    本文转自:https://www.cnblogs.com/kongxianghai/p/5582661.html Sequelize是一个基于promise的关系型数据库ORM框架,这个库完全采用Ja ...

  5. 百度图片objURL解密vb.net版

    Function Baidtu_Uncomplie(k As String) As String Dim c = {"_z2C$q", "_z&e3B" ...

  6. [Linux] 搭建rsync服务端

    rsync是unix/linux下同步文件的一个高效算法,它能同步更新两处计算机的文件与目录,并适当利用查找文件中的不同块以减少数据传输. Linux守护进程的运行方式:1.独立运行(stand-al ...

  7. 20190322-a标签、img标签、三列表、特殊字符实体、表格

    目录 1.a标签 a标签的属性 锚点 2.img标签 img标签的属性 图像热区 3.三列表 有序列表(Ordered List)     ol>li 无序列表(Unordered List)  ...

  8. OOCSS(面向对象的CSS)总结

    按钮样式库:buttons.css /* vue */ [v-cloak]{display: none} /* 滚动条 */ ::-webkit-scrollbar { width: 6px; hei ...

  9. 浏览器登录Dynamics 365 CE没毛病,程序连接却报错。

    摘要: 微软动态CRM专家罗勇 ,回复308或者20190308可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . 今天我做实验 ...

  10. iOS----------教你如何使用 GitHub Desktop

    1.先创建一个工程项目Test 2.创建一个仓库Repository 3.提交到master(记得写标题) 4.推送到github上 5.创建仓库Respository成功