您的位置:首页 > 编程语言 > C语言/C++

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


测试

测试结果如下图所示:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: