迭代器模式

来源:互联网 发布:asp生成静态页面源码 编辑:程序博客网 时间:2024/06/06 04:12

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

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

本程序的背景是两家餐厅合并了,他们分别用数组和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;elsereturn 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;elsereturn 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;即可

指针指针。

原创粉丝点击