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. 基本 SQL 之增删改查(二)

    上一篇文章中,我们介绍了 SQL 中最基本的 DML 语法,包括 insert 的插入数据.update 的更新数据.delete 的删除数据以及基本的查询语法,但大多比较简单不能解决我们日常项目中复 ...

  2. springboot集成下,mybatis的mapper代理对象究竟是如何生成的

    前言 开心一刻 中韩两学生辩论. 中:端午节是属于谁的? 韩:韩国人! 中:汉字是谁发明的? 韩:韩国人! 中:中医是属于谁的? 韩:韩国人! 中:那中国人到底发明过什么? 韩:韩国人! 前情回顾 M ...

  3. express中间件系统的基本实现

    一直觉得express的中间件系统这种流式处理非常形象,就好像加工流水线一样,每个环节都在针对同一个产品的不同部分完成自己的工作,最后得到一个成品.今天就来实现一个简易的[中间件队列]. 一. API ...

  4. C#多线程编程笔记

    在开发中经常有遇到因为程序执行的时间过长,而造成程序假死的情况,这是因为我们的程序是同步执行的,当执行到需要长时间的操作时,程序就会等待当前的操作完成,从而造成程序假死.C#的异步与多线程就是为了解决 ...

  5. FastReport编程方式给Picture控件赋值

    public Image BytesToImage(Byte[] buffer) { var ms = new MemoryStream(buffer, 0, buffer.Length); retu ...

  6. docker修改国内官方镜像

    在正常情况下,docker有一个默认连接的国外官方镜像,在国外的网友访问该官方镜像自然不成问题,但是国内毕竟不是国外,由于国情不同,中国的网络访问国外官方镜像网速一向很慢,而且往往还会遭遇断网的窘境, ...

  7. JAVA Swing 改变标题栏左上角默认咖啡图标

    前言 最近使用Java的swing开发了一个小程序,想要实现改变标题栏左上角的图标,找了网上的资料,经过了一个下午的尝试,都是未能成功,最后,终于是在Java的一本书上找到了结果 我只能说,网上的东西 ...

  8. 单元测试与Mockito

    1.什么是单元测试? 顾名思义单元测试就是对软件系统中最小的单元(函数.类)做测试,类似焊接电路板前对每个电容器(电子元器件)的测试.从软件测试分级来看,单元测试是最底层也是离程序员最近的一层,一般由 ...

  9. 搞懂 JavaScript 继承原理

    在理解继承之前,需要知道 js 的三个东西: 什么是 JS 原型链 this 的值到底是什么 JS 的 new 到底是干什么的 1. 什么是 JS 原型链? 我们知道 JS 有对象,比如 var ob ...

  10. 如何获取Debug Android Hash Key

    在接入FaceBook第三方登录的时候,需要获取Android Hash Key. Android Hash Key即密钥散列有两种,一种是开发秘钥散列,一种是发布秘钥散列.这里主要介绍如何获取开发秘 ...