PHP設計模式之裝飾模式

<?PHP
//裝飾模式定義:在沒必要改變原類文件和使用繼承的狀況下,動態地擴展一個對象的功能。它是經過建立一個包裝對象,也就是裝飾來包裹真實的對象。
//裝飾模式的特色:
// (1) 裝飾對象和真實對象有相同的接口。這樣客戶端對象就能以和真實對象相同的方式和裝飾對象交互。
// (2) 裝飾對象包含一個真實對象的引用(reference)
// (3) 裝飾對象接受全部來自客戶端的請求。它把這些請求轉發給真實的對象。
// (4) 裝飾對象能夠在轉發這些請求之前或之後增長一些附加功能。這樣就確保了在運行時,不用修改給定對象的結構就能夠在外部增長附加的功能。在面向對象的設計中,一般是經過繼承來實現對給定類的功能擴展。
//適用性:
// 如下狀況使用Decorator模式
// 1. 須要擴展一個類的功能,或給一個類添加附加職責。
// 2. 須要動態的給一個對象添加功能,這些功能能夠再動態的撤銷。
// 3. 須要增長由一些基本功能的排列組合而產生的很是大量的功能,從而使繼承關係變的不現實。
// 4. 當不能採用生成子類的方法進行擴充時。一種狀況是,可能有大量獨立的擴展,爲支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增加。另外一種狀況多是由於類定義被隱藏,或類定義不能用於生成子類。
// 優勢:
// 1. Decorator模式與繼承關係的目的都是要擴展對象的功能,可是Decorator能夠提供比繼承更多的靈活性。
// 2. 經過使用不一樣的具體裝飾類以及這些裝飾類的排列組合,設計師能夠創造出不少不一樣行爲的組合。
// 缺點:
// 1. 這種比繼承更加靈活機動的特性,也同時意味着更加多的複雜性。
// 2. 裝飾模式會致使設計中出現許多小類,若是過分使用,會使程序變得很複雜。
// 3. 裝飾模式是針對抽象組件(Component)類型編程。可是,若是你要針對具體組件編程時,就應該從新思考你的應用架構,以及裝飾者是否合適。固然也能夠改變Component接口,增長新的公開的行爲,實現「半透明」的裝飾者模式。在實際項目中要作出最佳選擇。
// 設計原則:
// 1. 多用組合,少用繼承。
// 利用繼承設計子類的行爲,是在編譯時靜態決定的,並且全部的子類都會繼承到相同的行爲。然而,若是可以利用組合的作法擴展對象的行爲,就能夠在運行時動態地進行擴展。
// 2. 類應設計的對擴展開放,對修改關閉。
// 裝飾者與適配者模式的區別編輯
// 1.關於新職責:適配器也能夠在轉換時增長新的職責,但主要目的不在此。裝飾者模式主要是給被裝飾者增長新職責的。
// 2.關於原接口:適配器模式是用新接口來調用原接口,原接口對新系統是不可見或者說不可用的。裝飾者模式原封不動的使用原接口,系統對裝飾的對象也經過原接口來完成使用。(增長新接口的裝飾者模式能夠認爲是其變種--「半透明」裝飾者)
// 3.關於其包裹的對象:適配器是知道被適配者的詳細狀況的(就是那個類或那個接口)。裝飾者只知道其接口是什麼,至於其具體類型(是基類仍是其餘派生類)只有在運行期間才知道。[1] 

/**
 * 裝扮抽象類 裝扮子類繼承實現打扮方法
 */
abstract class Decorate{
	//定義被裝扮人對象引用
	protected $presonObj;
	public function __construct($presonObj){
		$this->presonObj = $presonObj;
	}
	//強制子類實現打扮方法
	abstract public function dress();
}
/**
 * 裝扮類1
 */
class Decorate1 extends Decorate{
	public function dress(){
		echo "我是裝扮方法1".PHP_EOL;
		$this->presonObj->dress();
	}
}

/**
 * 裝扮類2
 */
class Decorate2 extends Decorate{
	public function dress(){
		echo "我是裝扮方法2".PHP_EOL;
		$this->presonObj->dress();
	}
}

/**
 * 裝扮類3
 */
class Decorate3 extends Decorate{
	public function dress(){
		echo "我是裝扮方法3".PHP_EOL;
		$this->presonObj->dress();
	}
}
/**
 * 被裝扮類
 */
class Presona {
	private $name;
	public function __construct($name){
		$this->name = $name;
	}

	public function dress(){
		echo "個人名字:".$this->name."裝扮完畢".PHP_EOL;
	}
}

//客戶端調用,注意:這裏是累計調用,以棧的形式,先進後出
$presona = new Presona("小菜");

$presona = new Decorate3($presona);

$presona = new Decorate2($presona);

$presona = new Decorate1($presona);

$presona->dress();
相關文章
相關標籤/搜索