迭代器模式

迭代器模式提供一种方法顺序访问聚合对象中的各个元素,而不暴露其内部的表示。

迭代器模式让我们能够游走于聚合内部的每一个元素,而不暴露其内部的表示。

本程序的背景是两家餐厅合并了,他们分别用数组和list保存其菜单,又都不想修改。服务员在报菜单的时候总是需要两种方法分别遍历两个菜单。此时定义迭代器,使得服务员可以用相同的方法遍历两个菜单。

#include <iostream>
#include <string>
#include <list>
using namespace std;

class Object
{
public:
	string fulei;
};
class MenuItem : public Object
{
public:
	string name;
	string description;
	bool vegetarian;
	double price;
	MenuItem(){ }

	MenuItem(string name, 
		string description, 
		bool vegetarian,
		double price)
	{
		this->name = name;
		this->description = description;
		this->vegetarian = vegetarian;
		this->price = price;
	}

	string getName()
	{
		return name;
	}
	string getDescription()
	{
		return description;
	}
	double getPrice()
	{
		return price;
	}
	bool isVegetarian()
	{
		return vegetarian;
	}
};

class Iterator
{
public:
	virtual bool hasNext() { return true;}
	virtual Object* next() = 0;
};
class Menu 
{
public:
	virtual Iterator* createIterator()= 0;
};
class DinerMenuIterator : public Iterator
{
public:
	const static int MAX_ITEMS = 6;
	MenuItem** items;
	int position;
	DinerMenuIterator(MenuItem** items)
	{
		this->items = items;
		position = 0;
	}
	virtual Object* next()
	{
		MenuItem* menuItem = items[position];
		position++;
		return menuItem;
	}
	virtual bool hasNext()
	{
		if(position >= MAX_ITEMS)
			return false;
		else
			return true;
	}
};
class DinerMenu : public Menu
{
public:
	const static int MAX_ITEMS = 6;
	int numberOfItems;
	MenuItem** menuItems;
	DinerMenu()
	{
		menuItems = new MenuItem*[MAX_ITEMS];
		numberOfItems = 0;
		addItem("Vegetarian BLT",
			"(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99);
		addItem("BLT",
			"Bacon with lettuce & tomato on whole wheat", false, 2.99);
		addItem("Soup of the day",
			"Soup of the day, with a side of potato salad", false, 3.29);
		addItem("Hotdog",
			"A hot dog, with saurkraut, relish, onions, topped with cheese",
			false, 3.05);
		addItem("Steamed Veggies and Brown Rice",
			"Steamed vegetables over brown rice", true, 3.99);
		addItem("Pasta",
			"Spaghetti with Marinara Sauce, and a slice of sourdough bread",
			true, 3.89);
	}
	void addItem(string name, string description, bool vegetarian, double price)
	{
		MenuItem* menuItem = new MenuItem(name, description, vegetarian, price);
		if(numberOfItems >= MAX_ITEMS)
		{
			cout << " sorry, menu is full! can't add item to menu" << endl;
		}
		else
		{
			menuItems[numberOfItems] = menuItem;
			numberOfItems = numberOfItems + 1;
		}
	}
	MenuItem** getMenuItems()
	{
		return menuItems;
	}
	virtual Iterator* createIterator()
	{
		return new DinerMenuIterator(menuItems);
	}
};

class PancakeHouseMenuIterator : public Iterator
{
public:
	list<MenuItem*>* items;
	list<MenuItem*>::iterator iter;
	PancakeHouseMenuIterator(list<MenuItem*>* items)
	{
		this->items = items;
		iter = items->begin();
	}
	virtual Object* next()
	{
		MenuItem* menuItem = (*iter);
		++iter;
		return menuItem;
	}
	virtual bool hasNext()
	{
		if(iter != items->end())
			return true;
		else
			return false;
	}

};
class PancakeHouseMenu : public Menu
{
public:
	list<MenuItem*>* menuItems;
	PancakeHouseMenu()
	{
		menuItems = new list<MenuItem*>();
		addItem("K&B's Pancake Breakfast", 
			"Pancakes with scrambled eggs, and toast", 
			true,
			2.99);

		addItem("Regular Pancake Breakfast", 
			"Pancakes with fried eggs, sausage", 
			false,
			2.99);

		addItem("Blueberry Pancakes",
			"Pancakes made with fresh blueberries",
			true,
			3.49);

		addItem("Waffles",
			"Waffles, with your choice of blueberries or strawberries",
			true,
			3.59);
		
	}
	void addItem(string name, string description, bool vegetarian, double price)
	{
		MenuItem* menuItem = new MenuItem(name, description, vegetarian, price);
		menuItems->push_back(menuItem);
	}
	list<MenuItem*>* getMenuItems()
	{
		return menuItems;
	}
	virtual Iterator* createIterator()
	{
		return new PancakeHouseMenuIterator(menuItems); 
	}
};

class Waitress
{
public:
	PancakeHouseMenu* pancakeHouseMenu;
	DinerMenu* dinerMenu;
	Waitress(PancakeHouseMenu* pancakeHouseMenu, DinerMenu* dinerMenu)
	{
		this->pancakeHouseMenu = pancakeHouseMenu;
		this->dinerMenu = dinerMenu;
	}
	void printMenu()
	{
		Iterator* pancakeHouseMenuIterator = pancakeHouseMenu->createIterator();
		Iterator* dinerMenuIterator = dinerMenu->createIterator();
		cout << "MENU\n---\nBREAKFAST" << endl;
		printMenu(pancakeHouseMenuIterator);
		cout << "LUNCH" << endl;
		printMenu(dinerMenuIterator);
	}
	void printVegetarianMenu()
	{
		printVegetarianMenu(pancakeHouseMenu->createIterator());
		printVegetarianMenu(dinerMenu->createIterator());
	}
	bool isItemVegetarian(string name)
	{
		Iterator* breakfastIterator = pancakeHouseMenu->createIterator();
		if(isItemVegetarian(name, breakfastIterator))
			return true;
		Iterator* dinnerIterator = dinerMenu->createIterator();
		if(isItemVegetarian(name, dinnerIterator))
			return true;
		return false;
	}
private:
	void printMenu(Iterator* iter)
	{
		while(iter->hasNext())
		{
			MenuItem* menuItem = (MenuItem*)iter->next();
			cout << menuItem->getName()<<", "<<menuItem->getPrice()<<"--"<< menuItem->getDescription()<<endl;
		}
	}
	void printVegetarianMenu(Iterator* iter)
	{
		while(iter->hasNext())
		{
			MenuItem* menuItem = (MenuItem*)iter->next();
			if(menuItem->isVegetarian())
			{
				cout<<menuItem->getName() <<"\t\t"<< menuItem->getPrice()<<"\t"<<menuItem->getDescription()<<endl;
			}
		}
	}

	bool isItemVegetarian(string name, Iterator* iter)
	{
		while(iter->hasNext())
		{
			MenuItem* menuItem = (MenuItem*)iter->next();
			if(menuItem->getName().compare(name) == 0)
				if(menuItem->isVegetarian())
					return true;
		}
		return false;
	}
};

int main()
{
	PancakeHouseMenu* pancakeHouseMenu = new PancakeHouseMenu();
	DinerMenu* dinerMenu = new DinerMenu();
	Waitress* waitress =  new Waitress(pancakeHouseMenu, dinerMenu);
	waitress->printMenu();
	return 0;
}

迭代器需要相同的父类,原本是可以用MenuItem作为其共有的父类,但是这样会造成嵌套,所以声明了一个Object类作为父类。让MenuItem继承自Object。这样就避免了嵌套。

后记:其实也不用声明一个新类,只要在比如由于Observer形成了嵌套,可以在最前面声明一个class Observer;即可

指针指针。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值