牛骨文教育服务平台(让学习变的简单)

组合模式

模式定义:

        组合模式允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。

      这个模式能够创建一个树形结构,在同一个结构中处理嵌套菜单和菜单项组。通过菜单和项放在相同结构中,我们创建了一个“整体/部分”层次结构,即由菜单和菜单项组成的对象树。使用组合结构,我们能把相同的操作应用在组合和个别对象上。换句话说,在大多数情况下,我们可以忽略对象组合和个别对象之间的差别。

模式结构:

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

请按任意键继续. . .