php模式之装饰者模式学习

<?php
//装饰器模式主要是两类对象--被装饰者和装饰器对象
//装饰器和被装饰者拥有一样的超类(接口)
//外层装饰对象重写公共方法,并委托调用内层方法。
interface Decorate
 {
   # code...
   public function display();
 }
  
 class Person implements Decorate
 {
  
   public $name;
  
   public function __construct($name)
   {
     $this->name = $name;
     echo ‘我叫‘.$name.‘我准备出门了<br>‘;
   }
  
   public function display()
   {
  
     echo ‘我出门了<br>‘;
   }
 }
 /**
 *装饰器1,和被装饰者一样都是属于Decorate接口的实现
 **/
  
 class Wash implements Decorate
 {
  
   private $compact;
     
   public function __construct(Decorate $compact)
   {
     $this->compact = $compact;
       
   }
  
   public function display()
   {
     echo ‘我是一个装饰器1,出门之前先换件衣服<br>‘;
     $this->compact->display();
   }
  
 }
/**
*装饰器2
**/
 class Dress implements Decorate
 {
  
   private $compact;
     
   public function __construct(Decorate $compact)
   {
     $this->compact = $compact;
       
   }
  
   public function display()
   {
        echo ‘我是一个装饰器2,换衣服之前,先洗把脸<br>‘;
     $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,把门锁了<br>‘;
   }
 }
  
  
 $person = new Person(‘韩梅梅‘);
 //开始装饰
  $dress = new Dress($person);
  
  $wash = new Wash($dress);
  
  $close = new Close($wash);
  
  $close->display();

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()方法之前,或之后添加逻辑了。

指的一提的是,最后返回的还是一个闭包对象,所以在最后执行了一次,相当于启动,内部就会依次联动。

单是文字确实难以理解,后续有时间会把代码补上。

由于作者水平有限,如有错误还望海涵。

时间: 2025-01-12 22:21:29

php模式之装饰者模式学习的相关文章

Java进阶篇设计模式之五-----外观模式和装饰器模式

前言 在上一篇中我们学习了结构型模式的适配器模式和桥接模式.本篇则来学习下结构型模式的外观模式和装饰器模式. 外观模式 简介 外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性. 简单的来说就是对外提供一个简单接口,隐藏实现的逻辑.比如常用电脑的电源键,我们只需按电源键,就可以让它启动或者关闭,无需知道它是怎么启动的(启动CPU.启动内存.启动硬盘),怎么关闭的(关闭硬盘.关闭内存.关闭CPU)

设计模式回顾:策略模式、代理模式、装饰者模式的区别

前言 设计模式有很多,但设计模式的目的是一致的,都是为了提升代码的可读性和可扩展性.设计模式都遵循一些基本的原则,设计模式是为了遵循这些原则而创造的工具. - 单一职责原则:就一个类而言,应该仅有一个引起它变化的原因.这一点是说,如果有一些类过于臃肿,承担了过多的职责,就应当分解他. - 开放-封闭原则:软件实体(类.模块.函数等)应该可以扩展,但是不可修改.这一点是说,拒绝硬编码,拒绝直接修改原有代码. - 依赖倒转原则:高层模块不应该以来低层模块.两个都应该以来抽象.抽象不应该依赖细节.细节

IOS设计模式之二(门面模式,装饰器模式)

本文原文请见:http://www.raywenderlich.com/46988/ios-design-patterns. 由 @krq_tiger(http://weibo.com/xmuzyq)翻译,如果你发现有什么错误,请与我联系谢谢. 门面(Facade)模式(译者注:facade有些书籍译为门面,有些书籍译为外观,此处译为门面) 门面模式针对复杂的子系统提供了单一的接口,不需要暴漏一些列的类和API给用户,你仅仅暴漏一个简单统一的API. 下面的图解释了这个概念: 这个API的使用者

代理模式与装饰器模式的区别

代理模式与装饰器模式的区别,主要大于,从使用者(客户端)的角度来看的: //装饰器的客户public class Client{ public static void main(String[] args){ //客户指定了装饰者需要装饰的是哪一个类 Component component = new Decorator(new ConcreteComponent()); - }}//代理的客户public class Client{ public static void main(String

Java 代理模式和装饰者模式的区别

装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案:代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用: 装饰模式应该为所装饰的对象增强功能:代理模式对代理的对象施加控制,并不提供对象本身的增强功能 二者的实现机制确实是一样的,可以看到他们的实例代码重复是很多的.但就语义上说,这两者的功能是相反的,模式的一个重要作用是简化其他程序员对你程序的理解, 你在一个地方写装饰,大家就知道这是在增加功能,你写代理,大家就知道是在限制, 虽然代码很可能相同,但如果你

结构型模式之装饰者模式

GitHub地址:https://github.com/zhangboqing/design-mode/tree/master/src/main/java/com/zbq 一.定义 装饰者模式(Decorator Pattern) :动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活.其别名也可以称为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合.根据翻译的不同,装饰模式也有人称之为"油漆工模式&quo

【设计者模式】装饰者模式

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能. 我们通过下面的实例来演示装饰器模式的用法.其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类. 介绍 意图:动态地给一个对象添加一些额外的职责.就增加功能来说,装饰器模式相比生成子类更为灵活. 主要解决:一般的,我们为了扩展一个

java代理模式与装饰者模式

静态代理和装饰者模式的区别: 先来看一下装饰者模式的定义:装饰者模式动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. 总结一下采用装饰者模式是为了增强或拓展原对象的功能. 而静态代理除了能够提供功能增强外(AOP增加日志监控等,但不提供原对象本身的增强功能)还通常起到了控制访问的作用. 另外装饰者模式适用于递归组合. 看见百度静态代理和装饰者模式的区别出来前几个博客实在是无力吐槽,连装饰者模式其实就是动态代理模式都有人说的出来.. 相关连接: https://sta

戏说模式之装饰者模式(游戏)

装饰者模式 定义 装饰者(Decorator)模式提供了一种方法,使得在不改变原有类的基础上可以动态的扩展一个对象的功能.即动态的将指着附加到对象上. 装饰者模式的特点 1. 装饰对象和被装饰对象实现了相同的接口.客户端可以不加区分的使用具体是装饰者实现还是被装饰者实现的接口中的方法. 2.装饰对象有一个被装饰对象的实例.这样客户端就可以把被装饰对象的实例委托给装饰对象进行数据加工. 3.装饰对象被创建后,用创建后对象的实例调用接口方法,第一次方法的实现是在被装饰对象内完成. 4.客户端调用装饰