1. 程式人生 > >設計模式C++實現——組合模式

設計模式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

請按任意鍵繼續. . .