PHP设计模式-装饰者模式

PHP设计模式-装饰者模式

学习背景:
  1. 学习 laravel 框架时,发现中间件功能可以即插即用,随意扩展。但又因为其过于灵活,加之没搞明白实现原理,以致于几次工作中碰壁。为搞懂其原理,在揭开其神奇的面纱时,学习到 laravel 的中间件功能是通过装饰者模式来实现的,于是就误打误撞学习了一个新的设计模式,即装饰者模式
模式介绍:
  1. 装饰者模式是在开放—关闭原则下实现动态添加或减少功能的一种方式
  2. 装饰类和被装饰类可以独立发展,不会相互耦合
  3. 装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能,以及动态撤销
代码示例:中间件原理
<?php

interface Middleware
{
    public static function handle(Closure $next);
}

class A implements Middleware
{
    public static function handle(Closure $next)
    {
        echo "A start part" . PHP_EOL;
        $next();
        echo "A end part" . PHP_EOL;
    }
}

class B implements Middleware
{
    public static function handle(Closure $next)
    {
        echo "B start part" . PHP_EOL;
        $next();
        echo "B start part" . PHP_EOL;
    }
}

function getSlice()
{
    return function ($stack, $pipe) {
        return function () use ($stack, $pipe) {
            return $pipe::handle($stack);
        };
    };
}

function then()
{
    $pipes = ["A", "B"];
    $firstSlice = function () {
        echo "respond data" . PHP_EOL;
    };
    $pipes = array_reverse($pipes);
    call_user_func(array_reduce($pipes, getSlice(), $firstSlice));
}

then();
//输出:
//A start part
//B start part
//respond data
//B start part
//A end part

  1. 示例代码中的call_user_func(array_reduce($pipes, getSlice(), $firstSlice));可能比较难理解。搞懂他们,我们还需要知道,call_user_func的作用是把第一个参数作为回调函数调用;array_reduce ( array $array , callable $callback , mixed $initial = null )的作用是将回调函数 callback 迭代地作用到 array 数组中的每一个单元中,从而将数组简化为单一的值。
  2. 假设参数不变的情况下,上面代码可以解析成:
call_user_func(function () {
    return A::handle(
        function () {
            return B::handle(
                function () {
                    echo "respond data" . PHP_EOL;
                }
            );
        }
    );
});
  1. 如果上面那段还不容易理解,你还可以把它看成:
call_user_func(function () {
    echo "A start part" . PHP_EOL;
    call_user_func(function () {
        echo "B start part" . PHP_EOL;
        call_user_func(function () {
            echo "respond data" . PHP_EOL;
        });
        echo "B start part" . PHP_EOL;
    });
    echo "A end part" . PHP_EOL;
});
扩展知识:
  1. 在实际框架中的大致原理即使如此。示例中的firstSlice闭包,在实际中的作用是将request对象分发给路由服务提供者来处理并获取到响应的结果
  2. 看完上面示例,也就搞懂了,什么在中间件里面,即可以获取到请求的参数,也可以拿到响应的值
  3. 看完示例,也就搞懂了,为什么参考资料都说 中间件 的实现模式像个洋葱了
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值