• 装饰器模式以及Laravel框架下的中间件应用


      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);
  • 相关阅读:
    关于pem与ppk格式的密钥的相互转换
    关于linux免密登录的配置及ssh客户端基于私钥文件的登录
    关于yum update和yum upgrade的区别
    Golang文件操作整理
    整理那些用于基本生存的shell命令
    Docker command line 学习笔记
    关于fork
    tips for using shortcuts
    chapter2
    使用MarkDown的编辑器
  • 原文地址:https://www.cnblogs.com/firstForEver/p/8001711.html
Copyright © 2020-2023  润新知