設計模式專題(三)——裝飾模式
設計模式專題(三)——裝飾模式
(原創內容,轉載請註明來源,謝謝)
一、概述
裝飾模式(Decorator)是指動態的給一個物件新增額外的職責,就增加功能來說,裝飾模式比生成子類更靈活。且裝飾模式會將需要的功能按正確的順序串聯起來控制。裝飾模式主要由幾部份組成。
1)Component抽象類,定義一個裝飾方法,繼承這個抽象類的類都需要實現裝飾方法decorate()。
2)ConcreteComponent類,繼承component,是具體裝飾方法實現的類。由該類實現將各種裝飾的方式組合起來。
3)Decorator抽象類,繼承component,其實現裝飾方法是通過傳入一個Component型別的物件,並執行其自身的decorate方法。
4)ConcreteDecorator類,繼承Decorator,起到給component新增職責的功能,即具體某一方面裝飾的功能。
二、功能
1)裝飾模式是為已有的功能動態的新增更多功能的一種方式。
2)裝飾模式把每個要要裝飾的功能放在單獨的類中,讓這個類包裝它所要裝飾的物件。當要執行特殊行為時,客戶端可以在執行時根據需要有選擇的、按順序的包裝物件。
3)把類中的功能從類中搬出,簡化原有的類。有效的把核心職責和裝飾功能分開,去除重複的裝飾邏輯。
三、場景
當要給一個類新增若干功能,這些功能之間互不相干,如果僅僅採用繼承,當需要載入十幾個功能,就需要十幾重的繼承,這樣程式碼沒法維護。當需要修改一個內容,會影響到非常多的類。
此時,就需要用到裝飾者模式,讓這些新增的內容類都繼承同一個父類,而這個父類又和原先待新增的類共同繼承一個類,這樣便於互相之間的呼叫。
四、UML類圖如下
五、實現
1、設計場景
現設計資料處理類,有一個字串和一個數組,字串和陣列分別需要經過選擇一種方式格式轉換、選擇一種方式加密。
因此,需要定義如下幾個類:
1)資料處理抽象類(DataDealer類形如上圖的component類)
2)資料處理實現類(DataDealerConcrete類形如上圖的concretecomponent類)
3)資料處理裝飾類(DataDecorator類形如上圖的decorator類)
4)資料處理具體裝飾類(TypeExchange、TransType類形如上圖concretedecoratorA、B類)
2、PHP實現如下
<?php
//實現裝飾模式,場景:資料處理
/*
現設計資料處理類,有一個字串和一個數組,
字串和陣列分別需要經過選擇一種方式格式轉換、選擇一種方式加密
因此,需要定義如下幾個類:
1)資料處理抽象類(DataDealer類)
2)資料處理實現類(DataDealerConcrete類)
3)資料處理裝飾類(DataDecorator類)
4)資料處理具體裝飾類(TypeExchange、TransType類)
*/
//資料處理抽象類
abstract class DataDealer{
private $method;//資料處理方法
public functiondeal(){}
}
//資料處理裝飾類
abstract class DataDecorator extends DataDealer{
private$dealIns;//datadealer的例項
private $method;//資料處理方法
public function__construct(DataDealer $dealIns, $method){
$this->dealIns= $dealIns;
$this->method= $method;
}
public functiondeal(){
$data =$this->dealIns->deal();
}
}
//資料處理具體類A——格式轉換
class TypeExchange extends DataDecorator{
private$dealIns;//datadealer的例項
private $method;//資料處理方法
public function__construct(DataDealer $dealIns, $method){
$this->dealIns= $dealIns;
$this->method= $method;
}
public functiondeal(){
$data = $this->dealIns->deal();
switch($this->method){
case'array2string'://陣列轉字串
$data= $this->array2string($data);
break;
case'string2array'://字串轉陣列
$data= $this->string2array($data);
break;
default:
break;
}
return$data;
}
private functionstring2array($data){}
private functionarray2string($data){
if(!is_array($data)){
return$data;
}
$str = '';
foreach($dataas $item){
if(is_array($item)){
$str.= $this->array2string($data);
}else{
$str.= $item . '|';
}
}
return $str;
}
}
//資料處理具體類B——序列化方式用於傳輸
class TransType extends DataDecorator{
private$dealIns;//datadealer的例項
private $method;//資料處理方法
public function__construct(DataDealer $dealIns, $method){
$this->dealIns= $dealIns;
$this->method= $method;
}
public functiondeal(){
$data = $this->dealIns->deal();
switch($this->method){
case'enjson'://json
$data= $this->enJson($data);
break;
case'enseria'://serialize
$data= $this->enSeria($data);
break;
default:
break;
}
return$data;
}
private functionenJson($data){
returnjson_encode($data);
}
private functionenSeria($data){
returnserialize($data);
}
}
//資料處理實現類
class DataDealerConcrete extends DataDealer{
private $data;
public function__construct($data){
$this->data= $data;
}
public functiondeal(){
return$this->data;
}
}
//客戶端,呼叫上述功能實現資料處理
$dataDealerString = new DataDealerConcrete('abcdefg');
$typeExchangeString = new TypeExchange($dataDealerString, 'none');
$transTypeString = new TransType($typeExchangeString, 'enjson');
var_dump($transTypeString->deal('abcdefg'));
$dataDealerArray = new DataDealerConcrete(array('a', 'b', 'c','d'));
$typeExchangeArray = new TypeExchange($dataDealerArray,'array2string');
$transTypeArray = new TransType($typeExchangeArray, 'enseria');
var_dump($transTypeArray->deal(array('a', 'b', 'c', 'd')));
——written by linhxx 217.07.28
相關閱讀: