## 模式定義:
? ? ? ? 組合模式允許你將對象組合成樹形結構來表現“整體/部分”層次結構。組合能讓客戶以一致的方式處理個別對象以及對象組合。
? ? ? 這個模式能夠創建一個樹形結構,在同一個結構中處理嵌套菜單和菜單項組。通過菜單和項放在相同結構中,我們創建了一個“整體/部分”層次結構,即由菜單和菜單項組成的對象樹。使用組合結構,我們能把相同的操作應用在組合和個別對象上。換句話說,在大多數情況下,我們可以忽略對象組合和個別對象之間的差別。
## 模式結構:

**Component:**
為組合中的對象聲明接口;
在適當情況下實現所有類共有接口的缺省行為;
聲明一個接口用于訪問管理Component的子組件
在遞歸結構中定義一個接口,用于訪問一個父部件,并在合適的情況下實現它
**Leaf:**
在組合中表示葉節點對象,葉節點沒有子節點,并定義其行為
**Composite:**
定義有子部件的那些部件的行為
存儲子部件
實現與子部件有關的操作
**Client:**
通過Component接口操作組合件和個別對象。
## 舉例:
? ? ? 在迭代器例子中,我們希望在午餐餐單中增加一份跌點餐單,也就是說希望能讓甜點餐單變成午餐餐單的一個元素。
? ? ? 我們可以用組合模式解決這個問題:一開始我們創建一個組件接口作為餐單和菜單項的共同接口,讓我們能夠用統一的做法來處理菜單和菜單項。換句話說,我們可以針對菜單或菜單項調用相同的方法。然后實現菜單項和組合菜單組件,以及他們各自的方法。
## UML設計:

## 編程實現及執行結果:
~~~
#include <iostream>
#include <vector>
#include <list>
#include <string>
using namespace std;
//菜單和菜單項共同的組件
class MenuComponent
{
public:
virtual void add(MenuComponent* menuComponent)
{
throw exception("add error!");
}
virtual void remove(MenuComponent* menuComponent)
{
throw exception("remove error!");
}
virtual MenuComponent* getChild(int i)
{
throw exception("getChild error");
}
virtual string getName()
{
throw exception("getName error");
}
virtual string getDescription()
{
throw exception("getDescription error");
}
virtual double getPrice()
{
throw exception("getPrice error");
}
virtual void print()
{
throw exception("print error");
}
};
//菜單項類
class MenuItem : public MenuComponent
{
public:
MenuItem(){}
MenuItem(string na, string descrip, double pric)
{
name = na;
description = descrip;
price = pric;
}
string getName()
{
return name;
}
string getDescription()
{
return description;
}
double getPrice()
{
return price;
}
void print()
{
cout << " " << getName() << ", " << getPrice()
<<" ---" << getDescription() << endl;
}
private:
string name;
string description;
double price;
};
//組合菜單類
class Menu : public MenuComponent
{
public:
Menu(string nam, string descri)
{
name = nam;
description = descri;
}
void add(MenuComponent* pMenuComponent)
{
pMenuComponents.push_back(pMenuComponent);
}
void remove(MenuComponent* pMenuComponent)
{
vector<MenuComponent*>::iterator iter = pMenuComponents.begin();
for(; iter!=pMenuComponents.end(); ++iter)
{
if(*iter == pMenuComponent)
{
pMenuComponents.erase(iter);
}
}
}
MenuComponent* getChild(int i)
{
return pMenuComponents[i];
}
string getName()
{
return name;
}
string getDescription()
{
return description;
}
void print()
{
cout << endl << getName() << ", " << getDescription() << endl << "--------------" << endl;
vector<MenuComponent*>::iterator iter = pMenuComponents.begin();
while(iter != pMenuComponents.end())
{
MenuComponent* pMenuComponent = *iter;
pMenuComponent->print();
++iter;
}
}
private:
vector<MenuComponent*> pMenuComponents;
string name;
string description;
};
//服務生類
class Waitress
{
public:
Waitress(MenuComponent* all_Menus)
{
allMenus = all_Menus;
}
void printMenu()
{
allMenus->print();
}
private:
MenuComponent* allMenus;
};
//客戶代碼
int main()
{
MenuComponent* pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU", "Breakfast");
MenuComponent* dinerMenu = new Menu("Diner MENU", "Lunch");
MenuComponent* dessertMenu = new Menu("DESSERT MENU","Dessert of coure!");
MenuComponent* allMenus = new Menu("ALL Menus", "All menus combined");
allMenus->add(pancakeHouseMenu);
allMenus->add(dinerMenu);
dinerMenu->add(new MenuItem("Pasta","Spaheti with Sauce", 3.89));
dinerMenu->add(dessertMenu);
dessertMenu->add(new MenuItem("Apple Pie", "App pie with a cruse", 1.59));
Waitress* waitress = new Waitress(allMenus);
waitress->printMenu();
return 0;
}
~~~
執行結果:
**ALLMenus,????? All menus combined**
**--------------**
****
**PANCAKEHOUSE MENU,???? Breakfast**
**--------------**
****
**DinerMENU,???? Lunch**
**--------------**
**Pasta,?3.89??? ---Spaheti with Sauce**
****
**DESSERTMENU,?? Dessert of coure!**
**--------------**
**Apple Pie,????? 1.59???---App pie with a cruse**
**請按任意鍵繼續. . .**