組合模式解析

組合模式:

將對象以樹形結構組織起來,以達成“部分-整體”的層次結構,使得客戶端對單個對象和組合對象的使用具有一致性。從定義中可以得到使用組合模式的環境爲:在設計中想表示對象的“部分-整體”層次結構;希望用戶忽略組合對象與單個對象的不同,統一地使用組合結構中的所有對象。

組合模式解耦了客戶程序與複雜元素內部結構,從而使客戶程序可以向處理簡單元素一樣來處理複雜元素。

如果你想要創建層次結構,並可以在其中以相同的方式對待所有元素,那麼組合模式就是最理想的選擇。

組合模式中必須提供對子對象的管理方法,不然無法完成對子對象的添加刪除等等操作,也就失去了靈活性和擴展性。但是管理方法是在Component中就聲明還是在Composite中聲明呢?

一種方式是在Component裏面聲明所有的用來管理子類對象的方法,以達到Component接口的最大化(如下圖所示)。目的就是爲了使客戶看來在接口層次上樹葉和分支沒有區別——透明性。但樹葉是不存在子類的,因此Component聲明的一些方法對於樹葉來說是不適用的。這樣也就帶來了一些安全性問題

另一種方式就是隻在Composite裏面聲明所有的用來管理子類對象的方法(如下圖所示)。這樣就避免了

上一種方式的安全性問題,但是由於葉子和分支有不同的接口,所以又失去了透明性

    

 在這一模式中,相對於安全性,我們比較強調透明性。對於第一種方式中葉子節點內不需要的方法可以

使用空處理或者異常報告的方式來解決。

優缺點

從上面的舉例中可以看到,組合模式有以下優點:

1)使客戶端調用簡單,客戶端可以一致的使用組合結構或其中單個對象,用戶就不必關心自己處理的

是單個對象還是整個組合結構,這就簡化了客戶端代碼。

2)容易在組合體內加入對象部件. 客戶端不必因爲加入了新的對象部件而更改代碼。這一點符合開閉

原則的要求,對系統的二次開發和功能擴展很有利!

當然組合模式也少不了缺點:組合模式不容易限制組合中的構件。

  1、Composite模式採用樹形結構來實現普遍存在的對象容器,從而將“一對多”的關係轉化爲“一對一”的關係,

使得客戶代碼可以一致的處理對象和對象容器,無需關心處理的是單個對象,還是組合的對象容器。

2、將“客戶代碼與複雜的對象容器結構”解耦是Composite模式的核心思想,解耦之後,客戶代碼將與純粹的

對象接口——而非對象容器的複雜內部實現結構——發生依賴關係,從而更能“應對變化”。

3、Composite模式中,是將“Add和Remove的和對象容器相關的方法”定義在“表示抽象對象的Component類”

中,還是將其定義在“表示對象容器的Composite類”中,是一個關乎“透明性”和“安全性”的兩難問題,需要仔

細權衡結構,這又是必須付出的代價。

4、Composite模式在具體實現中,可以讓父對象中的字對象反向追溯:如果父對象有頻繁的遍歷需求,可使

用緩存技巧來改善效率

class component {
     function descript(){}
     public function add(component $com){}
     public function remove(component $com){}
}
class dirComposite extends component{
    private $arrays=array();
    function descript(){
        echo "這是一枝幹";
    }

    function add(component $com){

      if(in_array($com,$this->arrays,true)){
           return;
      }
         $this->arrays[]=$com;
         return count($this->arrays);
    }
    function check($a,$b){
        return( $a === $b )?0:1;
    }
    function remove(component $com){
     $this->arrays=array_udiff($this->arrays,array($com),$this->check( $a , $b ));

    }
}
class fileLeaf extends component{
   function descript(){
        echo "這是一葉枝";
    }
}
class client {
    static function main(){
        $dir=new dirComposite();
        $file1=new fileLeaf();
        $file2=new fileLeaf();
        print_r($dir->add($file1));
    }
}
client::main();


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章