迭代器模式提供一种方法顺序访问聚合对象中的各个元素,而不暴露其内部的表示。
迭代器模式让我们能够游走于聚合内部的每一个元素,而不暴露其内部的表示。
本程序的背景是两家餐厅合并了,他们分别用数组和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;即可
指针指针。