当前位置: 首页 > 后端技术 > PHP

DecoratorPatternWithLaravelDecoratorPattern

时间:2023-03-29 23:34:57 PHP

DecoratorPattern装饰模式概述:1.初学者疑惑2.装饰模式的特点3.掌握装饰模式的简单案例4.装饰模式在laravel中的应用迷惑:开始学习之前laravel源码,我对“装饰器模式”知之甚少,“装饰器模式”的学习起源于创建一个中间件。我还是不太明白。中间件中的$next闭包是如何传入的,于是好奇又google了很多前辈的博客和文章,学到了很多以前不知道的知识点,才明白了中间件的原理loading,让我受益匪浅。感谢这些前辈们的无私奉献。好了,回到主题。详细介绍了装饰者模式的特点。”(1)装饰对象和真实对象有相同的接口。这样,客户端对象可以用同样的方式与真实对象通信。装饰对象交互。(2)装饰对象包含对真实对象的引用object(reference)(3)装饰对象接受来自客户端的所有请求。它将这些请求转发给真正的对象。(4)装饰对象可以在转发这些请求之前或之后添加一些额外的功能。这确保了在运行时,可以在不修改给定对象结构的情况下,从外部添加额外的功能,在面向对象设计中,通常通过继承功能扩展来实现给定类。》--------------引自<百度百科>简单案例掌握装饰器模式注意:如果你之前没有接触过这个模式,建议先看这篇文章《laravel 框架关键技术解析》学习笔记装饰器模式,回头看看这篇文章会更好。嗯,如果是第一次看装饰器模式,看看上面的特性“官方描述”,确实有点不清楚,ok,for为了方便大家快速了解该模式,我写了一个《laravel源码精简版》案例,放代码前,我会告诉大家实现该模式的核心东西,有两个方法,如下:call_user_func()如果你不明白,就给我指点array_reduce()你应该读它看看我的代码:$next();echo"Idon'tlikedicks";}}classguyimplementsfunc{publicstaticfunctionsay($next){echo'曾几何时是一个想找女朋友的程序员。$下一步();}}$e=[男人::类,美女::类];functiongetClosure(){returnfunction($a,$b){returnfunction()use($a,$b){$b::say($a);}};};}$d=function(){echo'找了半天,还是没有起色。突然有一天,我遇到了我最喜欢的女神。结果女神说:'."\n";};call_user_func(array_reduce($e,getClosure(),$d));不要着急看代码,先让代码跑起来,看看结果怎么样?然后分析代码,效果会更好。ok,照顾新手朋友,我给大家梳理一下执行过程。执行过程:第一步。首先,getClosure()函数调用返回一个闭包:function($a,$b){returnfunction()use($a,$b){return$b::say($a);}}第二步。使用$d和$e[0]作为第一步的参数返回结果并执行,返回结果:function()use($a,$b){#此时$b="guy"#$a=$d=function(){echo'找了好久,还是没有任何起色。突然有一天,我遇到了我最喜欢的女神。结果女神说:'."\n";}return$b::say($a);}第三步。使用第二部分的结果和$e[1]作为第一步的参数返回结果并执行。返回结果:function()use($a,$b){#此时$b="beauty"$a='第二步返回结果'#$a=function()use($,'beauty'){#beauty::say(function()use('guy',$d){#returnguy::say($d);#})#}return$b::say($a);}Step4.Executecall_user_func()andcallarray_reduce()toreturntheclosurethatistheresultofthirdstep.beauty::say($d)==>$d()=>echo'一个程序员曾经想找个女朋友。';=>echo"'找了很久,还是没有起色,突然有一天,遇到了喜欢的女神,结果,女神说:"=>"我不喜欢屌丝"执行过程和图片类似(仔细体会,像洋葱一样,从最外层渗透到最里层,再从最里层渗透到最外层):laravel在decorator模式下的应用,这里给出laravel框架源码对比分析,文件index.php第50行$kernel=$app->make(Illuminate\Contracts\Http\Kernel::class);$response=$kernel->handle($request=Illuminate\Http\Request::capture());文件Illuminate\Foundation\Http\Kernel.phppublicfunctionhandle($request){try{$request->enableHttpMethodParameterOverride();$response=$this->sendRequestThroughRouter($request);}catch(Exception$e){....省略异常处理}$this->app['events']->fire('kernel.handled',[$request,$response]);return$response;}保护函数sendRequestThroughRouter($request){$this->app->instance('request',$request);Facade::clearResolvedInstance('request');$this->bootstrap();返回(新管道($this->app))->send($request)->through($this->app->shouldSkipMiddleware()?[]:$this->middleware)->then($this->dispatchToRouter());}protectedfunctiondispatchToRouter(){returnfunction($request){$this->app->instance('request',$request);返回$this->router->dispatch($request);};}文件Illuminate\PipeLine\PipeLine.phppublicfunctionsend($passable){$this->passable=$passable;返回$这个;}publicfunctionthrough($pipes){$this->pipes=is_array($pipes)?$管道:func_get_args();返回$这个;}publicfunctionthen(Closure$destination){$firstSlice=$this->getInitialSlice($destination);$pipes=array_reverse($this->pipes);返回call_user_func(array_reduce($pipes,$this->getSlice(),$firstSlice),$this->passable);}protectedfunctiongetInitialSlice(Closure$destination){returnfunction($passable)use($destination){returncall_user_func($destination,$passable);}};}protectedfunctiongetSlice(){returnfunction($stack,$pipe){returnfunction($passable)use($stack,$pipe){//如果管道是一个闭包的实例,我们直接调用它但是//否则我们将解析容器外的管道并使用//适当的方法和参数调用它,返回结果。如果($pipeinstanceofClosure){returncall_user_func($pipe,$passable,$stack);}else{list($name,$parameters)=$this->parsePipeString($p个人资料);返回call_user_func_array([$this->container->make($name),$this->method],array_merge([$passable,$stack],$parameters));}};};}文件Illuminate\Foundation\Application.phppublicfunctionshouldSkipMiddleware(){return$this->bound('middleware.disable')&&$this->make('middleware.disable')===true;}