設計模式C++實現——組合模式
模式定義:
組合模式允許你將物件組合成樹形結構來表現“整體/部分”層次結構。組合能讓客戶以一致的方式處理個別對象以及物件組合。
這個模式能夠建立一個樹形結構,在同一個結構中處理巢狀選單和選單項組。通過選單和項放在相同結構中,我們建立了一個“整體/部分”層次結構,即由選單和選單項組成的物件樹。使用組合結構,我們能把相同的操作應用在組合和個別物件上。換句話說,在大多數情況下,我們可以忽略物件組合和個別物件之間的差別。
模式結構:
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
請按任意鍵繼續. . .