zoukankan      html  css  js  c++  java
  • 装饰器模式以及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);
  • 相关阅读:
    NS网络仿真,小白起步版,双节点之间的模拟仿真(基于UDP和CBR流)
    Linux学习,ACL权限管理
    SQL中的注释语句
    C#连接SQL Server数据库小贴士
    C#重写ToString
    C#控制台应用程序之选课系统
    浅谈C、C++及其区别、兼容与不兼容
    C++之客户消费积分管理系统
    A*算法
    HTML标签列表总览
  • 原文地址:https://www.cnblogs.com/firstForEver/p/8001711.html
Copyright © 2011-2022 走看看