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

本文介绍迭代器模式的基本概念,通过示例代码展示了如何为不同类型的菜单实现统一的遍历接口,使得服务员能够轻松地遍历各种菜单选项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义

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

要点

  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
测试

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值