C++设计模式十一--IteratorPattern(迭代器模式)
2017-06-28 11:46
369 查看
定义
迭代器模式提供一种方法顺序访问一个聚合(集合)对象中的各个元素,而又不暴露其内部的表示。要点
1.迭代器模式提供一种方法,可以顺序访问一个聚合(集合)对象中的元素,而又不用知道内部是如何表示的。2.迭代器将遍历聚合(集合)的工作封装进一个对象中。
3.当使用迭代器时,我们依赖聚合(集合)提供遍历。
4.迭代器提供了一个通用的接口,让我们遍历聚合(集合)的项,当我们编码使用聚合(集合)的项时,就可以使用多态机制。
5.迭代器模式把元素的遍历交给迭代器,而不是聚合(集合)对象。这不仅让聚合(集合)的接口和实现变得更简洁,也可以让聚合(集合)更专注它所应该专注的事情上面,而不必去理会遍历的事情。
类图
Aggregate:聚合(集合)接口,这对客户代码是很方便的,将客户代码从集合对象的实现解耦了。
ConcreteAggregate:具体聚合(集合)持有一个对象的集合,并实现一个方法(createIterator()),利用此方法返回集合的的迭代器。
Iterator:所有迭代器都必须实现的接口。它包含了一些方法,利用这些方法可以在集合元素之间游走。
ConcreteIterator:具体迭代器负责管理目前遍历的位置。
设计原则
单一责任:一个类应该只有一个引起变化的原因。1.修改一个类的代码的原因应该只有一个。
2.这个原则告诉我们将一个责任只指派给一个类。
3.当一个模块或一个类被设计成只支持一组相关的功能时,我们说它具有高内聚。
示例
下面通过实现两种不同餐厅菜单的迭代器,给服务员提供一个统一的遍历接口。Menu.h(Aggregate)
#ifndef MENU_H #define MENU_H #include "Iterator.h" namespace Iterator { class Menu { public: Menu(){} virtual ~Menu(){} virtual Iterator* createIterator() = 0; }; } #endif
MenuItem.h
#ifndef MENUITEM_H #define MENUITEM_H #include <iostream> #include <string> namespace Iterator { using std::cout; using std::endl; using std::string; class MenuItem { public: MenuItem(string n, int p): name(n), price(p) { } ~MenuItem(){} string getName() { return name; } int getPrice() { return price; } void print() { cout << getName() << ": " << getPrice() << endl; } private: string name; int price; }; } #endif
Breakfast.h (ConcreteAggregate)
#ifndef BREAKFAST_H #define BREAKFAST_H #include <iostream> #include <string> #include <vector> #include "Menu.h" #include "MenuItem.h" #include "Iterator.h" namespace Iterator { using std::cout; using std::endl; using std::string; using std::vector; class Breakfast: public Menu { public: Breakfast() { MenuItem *m1 = new MenuItem("Egg", 3); MenuItem *m2 = new MenuItem("Bread", 5); MenuItem *m3 = new MenuItem("Milk", 1); addMenuItem(m1); addMenuItem(m2); addMenuItem(m3); } ~Breakfast() { // need free memory } void addMenuItem(MenuItem *mi) { menu.push_back(mi); } Iterator *createIterator() { return new BreakfastIterator(menu); } private: vector<MenuItem *> menu; }; } #endif
Diner.h (ConcreteAggregate)
#ifndef DINER_H #define DINER_H #include <iostream> #include <string> #include "Menu.h" #include "MenuItem.h" #include "Iterator.h" namespace Iterator { using std::cout; using std::endl; using std::string; class Diner: public Menu { public: Diner(): menuCount(0) { MenuItem *m1 = new MenuItem("Meat", 10); MenuItem *m2 = new MenuItem("Fish", 20); MenuItem *m3 = new MenuItem("Steak", 50); addMenuItem(m1); addMenuItem(m2); addMenuItem(m3); } ~Diner() { // need free memory } void addMenuItem(MenuItem *mi) { menu[menuCount] = mi; menuCount++; } Iterator *createIterator() { return new DinerIterator(menu, menuCount); } private: MenuItem* menu[10]; int menuCount; }; } #endif
Iterator.h
#ifndef ITERATOR_H #define ITERATOR_H #include <vector> #include "MenuItem.h" namespace Iterator { using std::vector; // 迭代器接口 class Iterator { public: Iterator(){} virtual ~Iterator(){} virtual int hasNext() = 0; virtual MenuItem* next() = 0; }; // 午餐迭代器 (ConcreteIterator) class DinerIterator: public Iterator { public: DinerIterator(MenuItem *d[], int c): menuList(d), count(c), index(0) {} ~DinerIterator(){} int hasNext() { return index < count; } MenuItem* next() { MenuItem *m = menuList[index]; index++; return m; } private: MenuItem **menuList; int count; int index; }; // 早餐迭代器 (ConcreteIterator) class BreakfastIterator: public Iterator { public: BreakfastIterator(vector<MenuItem*> &mv) { menuVectorIterator = mv.begin(); end = mv.end(); } ~BreakfastIterator(){} int hasNext() { return (int)(menuVectorIterator != end); } MenuItem* next() { MenuItem *m = *(menuVectorIterator); menuVectorIterator++; return m; } private: vector<MenuItem *>::const_iterator menuVectorIterator; vector<MenuItem *>::const_iterator end; }; } #endif
Waitress.h (Client)
#ifndef WAITRESS_H #define WAITRESS_H #include "Menu.h" #include "Iterator.h" #include <iostream> namespace Iterator { using std::cout; using std::endl; class Waitress { private: Menu* m_pancakeHouseMenu; Menu* m_dinerMenu; private: void printMenu(Iterator* iterator) { while (iterator->hasNext()) { iterator->next()->print(); } } public: Waitress(Menu* pancakeHouseMenu, Menu* dinerMenu) { m_pancakeHouseMenu = pancakeHouseMenu; m_dinerMenu = dinerMenu; } ~Waitress() {} void printMenu() { Iterator *pancakeIterator = m_pancakeHouseMenu->createIterator(); Iterator *dinerIterator = m_dinerMenu->createIterator(); cout << "\nMenu\n========\nbreakfast:" << endl; printMenu(pancakeIterator); cout << "\nLunch:" << endl; printMenu(dinerIterator); delete pancakeIterator; delete dinerIterator; } }; } #endif
main.cpp
#include "Iterator.h" #include "Breakfast.h" #include "Diner.h" #include "Waitress.h" using namespace Iterator; int main() { Breakfast *b = new Breakfast(); Diner *d = new Diner(); Waitress* waitress = new Waitress(b, d); waitress->printMenu(); delete b; delete d; return 0; }
Makefile
CXX = g++ CFLAGS = -Wall LDFLAGS = target = res srcs = main.cpp objs = $(srcs:.cpp=.o) headers = $(wildcard *.h) .PHONY: all all: $(target) $(target): $(objs) $(headers) FORCE $(CXX) $(LDFLAGS) -o $(target) $(objs) -rm -f *.o ./$(target) $(objs):%.o:%.cpp $(CXX) $(CFLAGS) -c -o $@ $< .PHONY: FORCE FORCE: clean: rm -f $(target) *.o
测试
测试结果如下图所示:相关文章推荐
- 迭代器模式(Iterator Pattern)
- 设计模式笔记12:迭代器模式(Iterator Pattern)
- 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern)
- (第Ⅳ部分 行为型模式篇) 第17章 迭代器模式(Iterator Pattern)
- 设计模式 - 迭代器模式(iterator pattern) 具体解释
- 设计模式21:Iterator Pattern (迭代器模式)
- [转]迭代器模式(Iterator Pattern)
- 步步为营 .NET 设计模式学习笔记 十一、Iterator(迭代器模式)
- 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern)
- c++设计模式:迭代器模式(Iterator Pattern)
- 【17】迭代器模式(Iterator Pattern)
- 迭代器模式(Iterator Pattern)
- 迭代器模式(Iterator Pattern)
- 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern)
- JAVA设计模式之 迭代器模式【Iterator Pattern】
- 迭代器模式(Iterator Pattern)
- 迭代器模式(Iterator Pattern)
- 设计模式学习笔记---迭代器模式iterator pattern(Java版)
- .NET设计模式(18):迭代器模式(Iterator Pattern)(转)
- 设计模式之九:迭代器模式(Iterator Pattern)