ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
## 模式定义:         组合模式允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。       这个模式能够创建一个树形结构,在同一个结构中处理嵌套菜单和菜单项组。通过菜单和项放在相同结构中,我们创建了一个“整体/部分”层次结构,即由菜单和菜单项组成的对象树。使用组合结构,我们能把相同的操作应用在组合和个别对象上。换句话说,在大多数情况下,我们可以忽略对象组合和个别对象之间的差别。 ## 模式结构: ![](https://box.kancloud.cn/2016-08-30_57c54591e2a52.jpg) **Component:** 为组合中的对象声明接口; 在适当情况下实现所有类共有接口的缺省行为; 声明一个接口用于访问管理Component的子组件 在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它 **Leaf:** 在组合中表示叶节点对象,叶节点没有子节点,并定义其行为 **Composite:** 定义有子部件的那些部件的行为 存储子部件 实现与子部件有关的操作 **Client:** 通过Component接口操作组合件和个别对象。 ## 举例:       在迭代器例子中,我们希望在午餐餐单中增加一份跌点餐单,也就是说希望能让甜点餐单变成午餐餐单的一个元素。       我们可以用组合模式解决这个问题:一开始我们创建一个组件接口作为餐单和菜单项的共同接口,让我们能够用统一的做法来处理菜单和菜单项。换句话说,我们可以针对菜单或菜单项调用相同的方法。然后实现菜单项和组合菜单组件,以及他们各自的方法。 ## UML设计: ![](https://box.kancloud.cn/2016-08-30_57c545923b19a.jpg) ## 编程实现及执行结果: ~~~ #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** **请按任意键继续. . .**