【概述】
組合模式是將一系列對象組合成樹形結構用來表示整體和部分之間的關係,組合模式的主要目的是達到,訪問組合對象和訪問單個對象具有一致性。這裏的組合對象比較特殊,本身他可以是由其他的對象組合而成,同時,這個組合對象又可以是組成更復雜對象的一個部分。我們來舉個例子來說明吧,可能更直觀
【案例】
黑棗圖書公司的想把圖書分類以目錄的形式打印出來
【OOA】
組合模式將對象組合成樹形結構以表示“部分-整體”的層次結構。
設計OOD:
<UML>
<說明>
1、抽象角色(MenuComponent),給參加組合的對象規定一系列接口。接口中包括管理節點的方法
在本例中如add及remove方法。MenuComponent中可以定義一些接口的默認動作。
2、樹葉組件(Leaf)角色:在組合中表示葉節點對象,葉節點沒有子節點。在組合中定義圖元對象的行爲。
在本例中爲MenuItem,爲菜單的具體項,不可以有子項。
3、樹枝組件(Composite)角色:存儲子部件。定義有子部件的那些部件的行爲。在Component接口中實現與子部件有關的操作。
在本例中爲Menu,爲菜單項,菜單項包含了一個menuComponents數組來儲存MenuItem。
【OOP】
<代碼>
abstract class MenuComponent
{
public $name;
public abstract function getName();
public abstract function add(MenuComponent $menu);
public abstract function remove(MenuComponent $menu);
public abstract function getChild($i);
public abstract function show();
}
class MenuItem extends MenuComponent
{
public function __construct($name)
{
$this->name = $name;
}
public function getName(){
return $this->name;
}
public function add(MenuComponent $menu){
return false;
}
public function remove(MenuComponent $menu){
return false;
}
public function getChild($i){
return null;
}
public function show(){
echo " |-".$this->getName()."\n";
}
}
class Menu extends MenuComponent
{
public $menuComponents = array();
public function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
public function add(MenuComponent $menu)
{
$this->menuComponents[] = $menu;
}
public function remove(MenuComponent $menu)
{
$key = array_search($menu, $this->menuComponents);
if($key !== false) unset($this->menuComponents[$key]);
}
public function getChild($i)
{
if(isset($this->menuComponents[$i])) return $this->menuComponents[$i];
return null;
}
public function show()
{
echo ":" . $this->getName() . "\n";
foreach($this->menuComponents as $v){
$v->show();
}
}
}
【測試用例】:
<代碼>
class testDriver
{
public function run()
{
$menu1 = new Menu('文學');
$menuitem1 = new MenuItem('繪畫');
$menuitem2 = new MenuItem('書法');
$menuitem3 = new MenuItem('小說');
$menuitem4 = new MenuItem('雕刻');
$menu1->add($menuitem1);
$menu1->add($menuitem2);
$menu1->add($menuitem3);
$menu1->add($menuitem4);
$menu1->show();
}
}
$test = new testDriver();
$test->run();
<輸出>
小結:
組合模式解耦了客戶程序與複雜元素內部結構,從而使客戶程序可以向處理簡單元素一樣來處理複雜元素。
【常用情境】
1.想表示對象的部分-整體層次結構
2.希望用戶忽略組合對象與單個對象的不同,用戶將統一地使用組合結構中的所有對象。
【優點】
1、使客戶端調用簡單,客戶端可以一致的使用組合結構或其中單個對象,用戶就不必關係自己處理的是單個對象還是整個組合結構,這就簡化了客戶端代碼。
2、更容易在組合體內加入新對象部件. 客戶端不必因爲加入了新的對象部件而更改代碼。
【缺點 】
客戶端調用簡單靈活也帶來組合的限制問題。
【合成模式與其它模式】
1、裝飾器模式:Decorator模式經常與Composite模式一起使用。當裝飾與合成一起使用時,它們通常有一個公共的父類。因此裝飾必須支持具有add,remove和getChild操作的Component接口
2、享元模式:Flyweight模式讓你共享組件,但不再引用他們的父部件
3、迭代器模式:Itertor可用來遍歷Composite
4、訪問者模式:Visitor將本來應該分佈在Composite和Leaf類中的操作和行爲局部化。
********************************************
* 作者:葉文濤
* 標題:Php設計模式之【組合模式Composite Pattern】
* 參考:
*《設計模式:可複用面向對象軟件基礎 》(美)Erich Gamma 等著
*《Head First設計模式》Eric Freeman等著
*《PHP設計模式》Aaron Saray等著,樑志敏等譯(PS:翻譯的是狗屁水平)
******************轉載請註明網址來源 ***************