name = $name; echo '我叫'.$name.'我准备出门了
'; } public function display() { echo '我出门了
'; } } /** *装饰器1,和被装饰者一样都是属于Decorate接口的实现 **/ class Wash implements Decorate { private $compact; public function __construct(Decorate $compact) { $this->compact = $compact; } public function display() { echo '我是一个装饰器1,出门之前先换件衣服
'; $this->compact->display(); } } /** *装饰器2 **/ class Dress implements Decorate { private $compact; public function __construct(Decorate $compact) { $this->compact = $compact; } public function display() { echo '我是一个装饰器2,换衣服之前,先洗把脸
'; $this->compact->display(); } } /** *装饰器3 **/ class Close implements Decorate { private $compact; public function __construct(Decorate $compact) { $this->compact = $compact; } public function display() { $this->compact->display(); echo '我是装饰器3,把门锁了
'; } } $person = new Person('韩梅梅'); //开始装饰 $dress = new Dress($person); $wash = new Wash($dress); $close = new Close($wash); $close->display();
我们提供的服务有:成都网站建设、成都做网站、微信公众号开发、网站优化、网站认证、辉南ssl等。为上千企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的辉南网站制作公司
laravel中装饰器模式实现----中间件(middleware)
laravel中的实现方式可能与上面讲的不一样,但是其软件设计模式是相通的,通过对请求不断的装饰,
只是它装饰采用的是闭包传入的方式。
核心源码解析
/** * Send the given request through the middleware / router. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ protected function sendRequestThroughRouter($request) { $this->app->instance('request', $request); Facade::clearResolvedInstance('request'); $this->bootstrap(); return (new Pipeline($this->app)) //发送请求到管道中 ->send($request) //thtough()方法可以理解成在收集该请求过程中 //的中间键数组包括基础服务的和用户自定义的 ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter()); }
核心方法是在then() 我们接着来看then()里面的实现
/** * Run the pipeline with a final destination callback. * * @param \Closure $destination * @return mixed */ public function then(Closure $destination) { $pipeline = array_reduce( array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination) //这里$this->pipes即为要通过的中间件数组,$this->carray()是一个闭包处理函数。它会 //执行当前上一次传入的闭包,同时可以决定在执行前或执行后,插入逻辑(即中间件)。 //$this->prepareDestination($destination)也是一个闭包,可以理解成没用中间件的情况 //请求过程中会执行的 ); return $pipeline($this->passable); }
这里的难点和巧妙在于mixed array_reduce( array $array , callable $callback [, mixed $initial = NULL ] );
官方的说法是--array_reduce — 用回调函数迭代地将数组简化为单一的值。通俗一点讲就是以$callback遍历处理$array,每次传入的是上一次回调处理的函数和当前数组元素(是不是有点像装饰者,一层一层装饰);由于篇幅有限,具体使用和理解请参考手册。
这里比较难理解的是在传入参数上,laravel框架中传入的第一个参数---中间件对象数组 。它会使用上一次处理的结果(闭包对象$next),在根据自己的handle方法,该方法接受一个参数--$next,这样就可以在$next()方法之前,或之后添加逻辑了。
指的一提的是,最后返回的还是一个闭包对象,所以在最后执行了一次,相当于启动,内部就会依次联动。
单是文字确实难以理解,后续有时间会把代码补上。
由于作者水平有限,如有错误还望海涵。