装饰模式:动态的给对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加的灵活。
装饰者模式与传统模式的区别
一般要给对象添加功能时的做法:
传统模式:
(1)直接修改对象添加相应的功能,
(2)派生对应的子类来拓展原有类的功能
装饰者模式:
使用对象组合的方式,动态的组合功能
装饰者模式的具体做法
在这种模式下,对已有对象的部分内容或者是功能进行调整,但是不修改原始的对象结构。换句话说,不修改已有的类,而是通过创建另外一个装饰者类去动态的拓展其需要修改的内容。
优势:
(1)可以保证类的层次不会因过多而发生混乱
(2)当我们需求的修改很小时,不用改变原有的数据结构
装饰者模式把每个要装饰的功能放在单独的类中,并让这个类包装它需要装饰的对象。因此,当需要执行特殊行为时吗,客户端代码就可以在运行时根据需求有选择的,按顺序的的使用装饰功能来包装对象。有效的把类的核心职责和装饰功能区分开,而且可以去除相关类中重复的逻辑代码。
案例1
1 <?php 2 3 /** * 被修饰类 现在的需求: 要求能够动态为CD添加音轨、能显示CD音轨列表。 显示时应采用单行并且为每个音轨都以音轨好为前缀。 */ 4 5 6 class CD { 7 public $trackList; 8 9 function __construct() { 10 # code... 11 $this->trackList=array(); 12 } 13 14 public function addTrack($track){ 15 $this->trackList[]=$track; 16 } 17 18 public function getTrackList(){ 19 $output=" "; 20 foreach ($this->trackList as $key => $value) { 21 # code... 22 $output.=($key+1).") {$value}. "; 23 } 24 return $output; 25 } 26 27 } 28 29 /* 现在需求发生变化: 要求将当前实例输出的音轨都采用大写形式。 这个需求并不是一个变化特别大的需求,不需要修改基类或创建一个父子关系的子类,此时创建一个基于装饰器模式的装饰器类。 */ 30 31 class CDTrackListDecoratorCaps{ 32 private $_cd; 33 34 public function __construct(CD $CD){ 35 $this->_cd=$CD; 36 } 37 38 public function makeCaps(){ 39 foreach ($this->_cd->trackList as $key => $value) { 40 # code... 41 $this->_cd->trackList[$key]=strtoupper($value); //转换成大写 42 } 43 } 44 } 45 46 //客户端测试 47 $myCD=new CD(); 48 $trackList=array( "what It Means", "brr", "goodBye" ); 49 foreach ($trackList as $key => $value) { 50 # code... 51 $myCD->addTrack($value); 52 } 53 54 $myCDCaps=new CDTrackListDecoratorCaps($myCD); 55 $myCDCaps->makeCaps(); 56 print "The CD contains the following tracks:".$myCD->getTrackList();
案例2
1 UserInfo.php 2 //装饰器模式,对已有对象的部分内容或者功能进行调整,但是不需要修改原始对象结构,可以使用装饰器设计模式 3 class UserInfo { 4 5 public $userInfo = array(); 6 7 public function addUser($userInfo) { 8 $this->userInfo[] = $userInfo; 9 } 10 11 public function getUserList() { 12 print_r($this->userInfo); 13 } 14 } 15 16 //UserInfoDecorate 装饰一样,改变用户信息输出为大写格式,不改变原先UserInfo类 17 <?php 18 include("UserInfo.php"); 19 class UserInfoDecorate { 20 21 public function makeCaps($UserInfo) { 22 foreach ($UserInfo->userInfo as &$val) { 23 $val = strtoupper($val); 24 } 25 } 26 27 } 28 29 $UserInfo = new UserInfo; 30 $UserInfo->addUser('zhu'); 31 $UserInfo->addUser('initphp'); 32 $UserInfoDecorate = new UserInfoDecorate; 33 $UserInfoDecorate->makeCaps($UserInfo); 34 $UserInfo->getUserList();