当前位置 主页 > 服务器问题 > Linux/apache问题 >

    PHP设计模式之装饰器(装饰者)模式(Decorator)入门与应用详解

    栏目:Linux/apache问题 时间:2019-12-13 16:21

    本文实例讲述了PHP设计模式之装饰器(装饰者)模式(Decorator)入门与应用。分享给大家供大家参考,具体如下:

    通常情况下,我们如果要给对象添加功能,要么直接修改对象添加相应的功能,要么派生对应的子类来扩展,抑或是使用对象组合的方式。显然,直接修改对应的类这种方式并不可取。

    在面向对象的设计中,我们也应该尽量使用对象组合,而不是对象继承来扩展和复用功能。装饰器模式就是基于对象组合的方式,可以很灵活的给对象添加所需要的功能,并且它的本质就是动态组合,一句话,动态是手段,组合才是目的。

    也就是说,在这种模式下,我们可以对已有对象的部分内容或者功能进行调整,但是不需要修改原始对象结构,理解了不???

    还可以理解为,我们不去修改已有的类,而是通过创建另外一个装饰器类,通过这个装饰器类去动态的扩展其需要修改的内容。而它的好处也是显而易见的,如下:

    1、我们可以保证类的层次不会因过多而发生混乱。 2、当我们需求的修改很小时,不用改变原有的数据结构。

    我们来看下《PHP设计模式》里面的一个案例:

    /** * 被修饰类 现在的需求: 要求能够动态为CD添加音轨、能显示CD音轨列表。 显示时应采用单行并且为每个音轨都以音轨好为前缀。 */
    class CD {
      public $trackList;
      function __construct()  {
        # code...
        $this->trackList=array();
      }
      public function addTrack($track){
        $this->trackList[]=$track;
      }
      public function getTrackList(){
        $output=" ";
        foreach ($this->trackList as $key => $value) {
          # code...
          $output.=($key+1).") {$value}. ";
        }
        return $output;
      }
    }
    /* 现在需求发生变化: 要求将当前实例输出的音轨都采用大写形式。 这个需求并不是一个变化特别大的需求,不需要修改基类或创建一个父子关系的子类,此时创建一个基于装饰器模式的装饰器类。 */
    class CDTrackListDecoratorCaps{
      private $_cd;
      public function __construct(CD $CD){
        $this->_cd=$CD;
      }
      public function makeCaps(){
        foreach ($this->_cd->trackList as $key => $value) {
          # code...
          $this->_cd->trackList[$key]=strtoupper($value); //转换成大写
        }
      }
    }
    //客户端测试
    $myCD=new CD();
    $trackList=array(  "what It Means",  "brr",  "goodBye" );
    foreach ($trackList as $key => $value) {
      # code...
      $myCD->addTrack($value);
    }
    $myCDCaps=new CDTrackListDecoratorCaps($myCD);
    $myCDCaps->makeCaps();
    print "The CD contains the following tracks:".$myCD->getTrackList();
    
    

    来看一个比较通俗但是比较简单的案例:

    设计一个UserInfo类,里面有UserInfo数组,用于存储用户名信息 通过addUser来添加用户名 getUserList方法将打印出用户名信息 现在需要将添加的用户信息变成大写的,我们需要不改变原先的类,并且不改变原先的数据结构 我们设计了一个UserInfoDecorate类来完成这个需求的操作,就像装饰一样,给原先的数据进行了装修 装饰器模式有些像适配器模式,但是一定要注意,装饰器主要是不改变现有对象数据结构的前提

    代码如下:

    UserInfo.php

    //装饰器模式,对已有对象的部分内容或者功能进行调整,但是不需要修改原始对象结构,可以使用装饰器设计模式
    class UserInfo {
     public $userInfo = array(); 
     
     public function addUser($userInfo) {
     $this->userInfo[] = $userInfo;
     }
     
     public function getUserList() {
     print_r($this->userInfo);
     }
    }