裝飾者模式的定義php
文章連接:http://www.hcoding.com/?p=101ide
我的站點:http://www.hcoding.com/post
在沒必要改變原類文件和使用繼承的狀況下,動態地擴展一個對象的功能。它是經過建立一個包裝對象,也就是裝飾來包裹真實的對象。學習
裝飾者模式把每一個要裝飾的功能放在單獨的類中,並讓這個類包裝它要裝飾的對象,所以,當須要執行特殊行爲時,客戶端代碼就能夠在運行的時候根據須要有選擇地、按順序地使用裝飾功能包裝對象了。ui
圖1this
使用場景spa
設想一下,若是咱們須要建立一個在不一樣場合有不一樣着裝的學生,例如:在學校學生須要穿上校服,在舞會學生須要穿上正裝,在家學生能夠裸裝(有點變態),固然,還能夠學習超人把底褲穿在外面。這時候問題來了,難道咱們要爲每種場合編寫一個不一樣穿着的學生類嗎?若是咱們的童鞋想要一個穿着校服褲子、正裝上衣外露的底褲怎麼辦?StudentWithSchoolUniform、StudentWithFormalWear、StudentWithNaked、StudentWithSchoolUniformAndOutSideUnderWear..................綿綿無盡的類~~~累!是的,若是這樣就形成類爆炸了,需求增長,類就不斷的增長,整個系統的維護難度可想而知。
pwa
因此這時候,裝飾者模式就能夠發揮它的做用了,底褲、正裝、校服、鞋子、眼鏡等等都是具體的裝飾者,學生是具體的被裝飾的對象,被裝飾的對象和裝飾者的抽象類都繼承者同一個父類。爲學生穿上不一樣的服裝,其實就是使用裝飾者類(服裝)包裹被裝飾者類(學生),形象的說這是一個穿衣的過程。設計
類和接口3d
例子
圖2
Person.php
1 <?php 2 3 /** 4 * Person.php 5 * 被裝飾基類 6 **/ 7 abstract class Person{ 8 9 public abstract function show(); 10 11 }
Student.php
1 <?php 2 3 /** 4 * Student.php 5 * 具體被裝飾對象 6 **/ 7 class Student extends Person{ 8 9 private $name; 10 11 public function __construct($name){ 12 $this->name = $name; 13 } 14 15 public function show(){ 16 echo '我是學生',$this->name; 17 } 18 }
Costume.php
1 <?php 2 3 /** 4 * Costume.php 5 * 裝飾者基類 6 **/ 7 abstract class Costume extends Person{ 8 9 10 }
Shirt.php
1 <?php 2 3 /** 4 * Shirt.php 5 * 具體的裝飾者類 6 **/ 7 class Shirt extends Costume{ 8 9 private $person; 10 11 public function __construct(Person $person){ 12 13 $this->person = $person; 14 15 } 16 17 public function show(){ 18 19 echo $this->person->show(),',穿着襯衫'; 20 } 21 22 }
Pants.php
1 <?php 2 3 /** 4 * Pants.php 5 **/ 6 class Pants extends Costume{ 7 8 private $person; 9 10 public function __construct(Person $person){ 11 12 $this->person = $person; 13 14 } 15 16 public function show(){ 17 18 echo $this->person->show(),',穿着褲子'; 19 } 20 21 }
Glasses.php
1 <?php 2 3 /** 4 * Glasses.php 5 **/ 6 class Glasses extends Costume{ 7 8 private $person; 9 10 public function __construct(Person $person){ 11 12 $this->person = $person; 13 14 } 15 16 public function show(){ 17 18 echo $this->person->show(),',帶着眼鏡'; 19 } 20 21 }
UnderWear.php
1 <?php 2 3 /** 4 * UnderWear.php 5 **/ 6 class UnderWear extends Costume{ 7 8 private $person; 9 10 public function __construct(Person $person){ 11 12 $this->person = $person; 13 14 } 15 16 public function show(){ 17 18 echo $this->person->show(),',穿着DK'; 19 } 20 21 }
Client.php
1 <?php 2 3 require_once 'Person.php'; 4 require_once 'Costume.php'; 5 require_once 'Student.php'; 6 require_once 'UnderWear.php'; 7 require_once 'Shirt.php'; 8 require_once 'Pants.php'; 9 require_once 'Glasses.php'; 10 11 // Student繼承Person 12 $jc = new Student('JC'); 13 $jc->show(); // 我是學生JC 14 echo '<br>'; 15 16 // 用UnderWear類裝飾Person 17 $underwear = new UnderWear($jc); 18 $underwear->show(); // 我是學生JC,穿着DK 19 echo '<br>'; 20 21 // 再用Pants類裝飾Person 22 $pants = new Pants($underwear); 23 $pants->show(); // 我是學生JC,穿着DK,穿着褲子 24 echo '<br>'; 25 26 // 再用Shirt類裝飾Person 27 $shirt = new Shirt($pants); 28 $shirt->show(); // 我是學生JC,穿着DK,穿着褲子,穿着襯衫 29 echo '<br>'; 30 31 // 再用Glasses類裝飾Person 32 $glasses = new Glasses($shirt); 33 $glasses->show(); // 我是學生JC,穿着DK,穿着褲子,穿着襯衫,帶着眼鏡 34 echo '<br>';
圖3 輸出結果截圖
Symfony2 EventDispatch 組件對裝飾者模式的應用
圖4 Symfony2 EventDispatch組件使用裝飾模式
圖5 Framework配置EventDispatcher
具體裝飾者對象Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher::dispatch()方法,核心依舊是調用被裝飾的具體對象Symfony\Component\EventDispatcher\EventDispatcher::dispatch()方法進行工做,可是裝飾者對象Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher::dispatch()方法添加了相應的功能,例如在調用Symfony\Component\EventDispatcher\EventDispatcher::dispatch()方法先後分別調用了preProcess()、preDispatch()和postDispatch()、postProcess():
1 /** 2 * {@inheritdoc} 3 */ 4 public function dispatch($eventName, Event $event = null) 5 { 6 if (null === $event) { 7 $event = new Event(); 8 } 9 10 // 裝飾者對象增長的功能 11 $this->preProcess($eventName); 12 $this->preDispatch($eventName, $event); 13 14 $e = $this->stopwatch->start($eventName, 'section'); 15 16 // 核心依舊是調用被裝飾的具體對象Symfony\Component\EventDispatcher\EventDispatcher::dispatch()方法 17 $this->dispatcher->dispatch($eventName, $event); 18 19 if ($e->isStarted()) { 20 $e->stop(); 21 } 22 23 // 裝飾者對象增長的功能 24 $this->postDispatch($eventName, $event); 25 $this->postProcess($eventName); 26 27 return $event; 28 }
優勢
缺點