C++设计模式十一--IteratorPattern(迭代器模式)

来源:互联网 发布:淘宝店铺流量来源查询 编辑:程序博客网 时间:2024/06/05 19:42

定义

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

要点

  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 = -WallLDFLAGS = target = ressrcs = main.cppobjs = $(srcs:.cpp=.o)headers = $(wildcard *.h).PHONY: allall: $(target)$(target): $(objs) $(headers) FORCE    $(CXX) $(LDFLAGS) -o $(target) $(objs)    -rm -f *.o    ./$(target)$(objs):%.o:%.cpp    $(CXX) $(CFLAGS) -c -o $@ $<.PHONY: FORCEFORCE: clean:    rm -f $(target) *.o

测试

测试结果如下图所示:
这里写图片描述