迭代器模式

最后更新于:2022-04-01 20:29:36

## 模式定义 迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。 迭代器模式让我们能游走于聚合内的每一个元素,而又不暴露其内部的表示。把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。 ## 模式结构: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c545916c8cc.jpg)       Iterator:迭代器定义访问和遍历元素的接口       ConcreteIterator:具体迭代器实现迭代器接口;对该聚合遍历时跟踪当前位置       Aggregate:聚合定义创建相应的迭代器对象接口       ConcreteAggregate:具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例。 ## 举例:       煎饼屋和午餐店合并后需要定制一份新的餐单,但由于煎饼屋的原菜单是用链表实现,而午餐点原菜单是用数组实现(他们的定义如下所示),所以打印新餐单的时候需要分别循环遍历原餐单中的菜单项。 ~~~ //菜单项类 class MenuItem { 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; } private: string name; string description; double price; }; //煎饼屋餐单类 class PancakeHouseMenu { public: PancakeHouseMenu() { addItem("K&B'S Breakfase","pacakes with eggs",2.99); addItem("Buleberry Breakfase","pacakes with buleberries",3.99); } void addItem(string na, string descrip, double ric) { MenuItem menuItem(na,descrip,ric); menuItems.push_back(menuItem); } list getMenuItems() { return menuItems; } private: list menuItems; }; //午餐点餐单类 class DinerMenu { public: DinerMenu() { addItem("Vegetarian BLT", "Bacon with lettuce", 2.99); addItem("BLT", "Bacon with tomato", 3.99); } void addItem(string na, string descrip, double ric) { MenuItem menuItem(na,descrip,ric); menuItems.push_back(menuItem); } vector getMenuItems() { return menuItems; } private: vector menuItems; }; //必须调用pancakeHouseMenu.getMenuItems()和//dinerMenu.getMenuItems()来取得他们的餐单 PancakeHouseMenu pancakeHouseMenu; list breakfastItems = pancakeHouseMenu.getMenuItems(); DinerMenu dinerMenu; vector lunchItem = dinerMenu.getMenuItems(); list::iterator iter = breakfastItems.begin(); //打印新餐单的时候需要分别循环遍历原餐单中的菜单项 for(; iter != breakfastItems.end(); ++iter) { MenuItem menuItem = *iter; cout << menuItem.getName() << " "<< menuItem.getPrice()<<" " << menuItem.getDescription() << endl; } for(unsigned int i=0; i #include #include #include using namespace std; //菜单项类 class MenuItem { 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; } private: string name; string description; double price; }; //迭代器基类 class Iterator { public: //是否有下一个一个菜单 virtual bool hasNext(){throw std::exception("ERROR");}; //取下一个菜单 virtual MenuItem next(){throw std::exception("ERROR");}; }; //煎饼屋餐单迭代器 class PancakeHouseMenuIterator : public Iterator { public: PancakeHouseMenuIterator(list item) { items = item; iter = items.begin(); } MenuItem next() { MenuItem menuItem = *iter; ++iter; return menuItem; } bool hasNext() { if(iter == items.end()) { return false; } else { return true; } } private: list items; list::const_iterator iter; }; //午餐店餐单迭代器 class DinerMenuIterator : public Iterator { public: DinerMenuIterator(vector item):position(0) { items = item; } MenuItem next() { MenuItem menuItem = items[position]; position = position + 1; return menuItem; } bool hasNext() { if(position >= items.size()) { return false; } else { return true; } } private: vector items; unsigned int position; }; //餐单基类 class Menu { public: //创建迭代器 virtual Iterator* createIterator(){throw std::exception("ERROR");} }; //煎饼屋餐单类 class PancakeHouseMenu : public Menu { public: PancakeHouseMenu() { addItem("K&B'S Breakfase","pacakes with eggs",2.99); addItem("Buleberry Breakfase","pacakes with buleberries",3.99); } //增加菜单 void addItem(string na, string descrip, double ric) { MenuItem menuItem(na,descrip,ric); menuItems.push_back(menuItem); } //创建PancakeHouseMenuIterator迭代器 Iterator* createIterator() { return new PancakeHouseMenuIterator(menuItems); } private: list menuItems; }; //午餐点餐单类 class DinerMenu : public Menu { public: DinerMenu() { addItem("Vegetarian BLT", "Bacon with lettuce", 2.99); addItem("BLT", "Bacon with tomato", 3.99); } void addItem(string na, string descrip, double ric) { MenuItem menuItem(na,descrip,ric); menuItems.push_back(menuItem); } Iterator* createIterator() { return new DinerMenuIterator(menuItems); } private: vector menuItems; }; //服务生类 class Waitress { public: Waitress(Menu* p_PancakeHouseMenu, Menu* p_DinerMenu) { pPancakeHouseMenu = p_PancakeHouseMenu; pDinerMenu = p_DinerMenu; } //打印菜单 void printMenu() { Iterator* pPancakeHouseIterator = pPancakeHouseMenu->createIterator(); Iterator* pDinerIterator = pDinerMenu->createIterator(); cout << "Menu"<< endl <<"----"<hasNext()) { MenuItem menuItem = (MenuItem)iter->next(); cout << menuItem.getName() << " "<< menuItem.getPrice()<<" " << menuItem.getDescription() << endl; } } private: Menu* pPancakeHouseMenu; Menu* pDinerMenu; }; //客户代码 int main() { Menu* pPancakeHouseMenu = new PancakeHouseMenu(); Menu* pDinerMenu = new DinerMenu(); Waitress waitress(pPancakeHouseMenu,pDinerMenu); waitress.printMenu(); return 0; } ~~~ 执行结果: **Menu** **----** **BREAKFAST** **K&B'SBreakfase 2.99    pacakes with eggs** **BuleberryBreakfase     3.99    pacakes with buleberries** **LUNCH** **VegetarianBLT  2.99    Bacon with lettuce** **BLT     3.99   Bacon with tomato** **请按任意键继续. . .** ## 设计原则的应用:       设计原则:一个类应该只有一个引起变化的原因。这个原则告诉我们尽量让一个类保持单一责任。如果一个类具有两个以上改变的原因,那么这会使将来该类的变化率上升。
';