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. 基于 Nginx 的 HTTPS 性能优化实践

    前言 分享一个卓见云的较多客户遇到HTTPS优化案例. 随着相关浏览器对HTTP协议的“不安全”.红色页面警告等严格措施的出台,以及向 iOS 应用的 ATS 要求和微信.支付宝小程序强制 HTTPS ...

  2. ASP.NET MVC5多语言切换快速实现方案

    功能 实现动态切换语言,Demo做了三种语言库可以切换,包括资源文件的定义,实体对象属性设置,后台代码Controller,IAuthorizationFilter,HtmlHelper的实现,做法比 ...

  3. Java提高班(六)反射和动态代理(JDK Proxy和Cglib)

    反射和动态代理放有一定的相关性,但单纯的说动态代理是由反射机制实现的,其实是不够全面不准确的,动态代理是一种功能行为,而它的实现方法有很多.要怎么理解以上这句话,请看下文. 一.反射 反射机制是 Ja ...

  4. Service Worker MDN英文笔记

    前言: 以前学习基础知识的时候总看别人写的入门文章,但有时候还是一脸懵逼,直到自己用心阅读了MDN的英文文档才对基础知识的一些理论有了更深的理解,所以我在边阅读文档的时候边记录下帮助比较大的,也方便大 ...

  5. 【.NET Core项目实战-统一认证平台】第十二章 授权篇-深入理解JWT生成及验证流程

    [.NET Core项目实战-统一认证平台]开篇及目录索引 上篇文章介绍了基于Ids4密码授权模式,从使用场景.原理分析.自定义帐户体系集成完整的介绍了密码授权模式的内容,并最后给出了三个思考问题,本 ...

  6. .Net语言 APP开发平台——Smobiler学习日志:如何快速实现按钮组功能

    最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的“Smobil ...

  7. C# 通过进程名/进程Id 操作窗口/程序

    1. 判断窗口是否存在 private bool IsWindowExist(IntPtr handle) { ) != IntPtr.Zero) && IsWindowVisible ...

  8. [Go] golang类型断言

    类型断言有点像向下转型,接口类型转到具体的实现实例类型上类型断言是一个使用在接口值上的操作.语法上它看起来像x.(T)被称为断言类型,这里x表示一个接口的类型和T表示一个类型 package main ...

  9. [Go] 并发和并行的区别

    并发和并行的区别:1.并行是让不同的代码片段同时在不同的物理机器上运行,并行的关键是在不同的物理机器上同时运行 2.并发是同时管理很多事情,比如在一个物理机器上进行不停的调度,有些事情可能只做了一半就 ...

  10. 高效使用VSCode的9点建议

    在开源 IDE 市场,最近几年 Visual Studio Code(简称 VSCode)越来越流行.自从 2015 年对外发布后,根据 2018 年 Stack Overflow 的调查报告,有 3 ...