Published on

设计模式(16)——迭代器 Iterator

Authors
  • avatar
    Name
    Leon
    Twitter

十六、Iterator(迭代器模式,别名 Cursor 游标)

1. 意图:

  提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示。

2. 适用:

  1. 访问一个聚合对象的内容而无需暴露它的内部表示
  2. 支持对聚合对象的多种遍历
  3. 为遍历不同的聚合结构提供一个统一的接口(即,支持多态迭代)

3. 类图:

4. 例:

  STL 模板库的中常见的容器类有List,Set,Map等,使用容器类经常需要遍历里面的所有元素,当对容器类中元素的组织方式不清楚时,要遍历元素不是一件容易的事情。迭代器就是解决这个问题的救星,它提供了一套统一的接口,如 begin(), next(), end(),所有的遍历都可以用这套接口来实现。这套接口具体由每个容器类来实现,容器内部才是最清楚怎么遍历自己元素的地方。正向遍历,反向遍历,中序遍历的需求可以通过由容器内部创建不同的 Iterator 来实现,而 Iterator 暴露的接口是一样的。

5. 中间层思考:

  通过引入 Iterator 迭代器这个中间层,系统可以不需要直接操作容器的所有细节,只需要知道 Iterator 的标准接口就能操作容器的所有元素。Iterator 将系统和容器的细节解耦了,程序猿的生活也变得更加美好了。

6. C++实现:

  1. 编写聚合类接口 Aggreagte,聚合类 ConcreteAggregate
  2. 编写迭代器接口 Iterator,迭代器类 ConcreteIterator,含有方法 First()Next()CurrentItem()IsDone()
  3. 编写迭代器构造函数 ConcreteIterator(Aggregate* ag, int idx = 0),强关联一个聚合类对象。

Iterator.h

//Iterator.h
#pragma once

typedef int Object;

class Aggregate;

class Iterator {
public:
	virtual ~Iterator();
	virtual void First() = 0;
	virtual void Next() = 0;
	virtual bool IsDone() = 0;
	virtual Object CurrentItem() = 0;
protected:
	Iterator();
private:
};

class ConcreteIterator : public Iterator {
public:
	ConcreteIterator(Aggregate* ag, int idx = 0);
	~ConcreteIterator();
	void First();
	void Next();
	bool IsDone();
	Object CurrentItem();
protected:
private:
	Aggregate* _ag;
	int _idx;
};

Iterator.cpp

//Iterator.cpp
#include "Iterator.h"
#include "Aggregate.h"

#include <iostream>
using namespace::std;

Iterator::Iterator() {}
Iterator::~Iterator() {}

ConcreteIterator::ConcreteIterator(Aggregate* ag, int idx) {
	this->_ag = ag;
	this->_idx = idx;
}
ConcreteIterator::~ConcreteIterator() {}
Object ConcreteIterator::CurrentItem() {
	return _ag->GetItem(_idx);
}
// 初始化迭代器
void ConcreteIterator::First() {
	_idx = 0;
}
void ConcreteIterator::Next() {
	if (_idx < _ag->GetSize())
		_idx++;
}
bool ConcreteIterator::IsDone() {
	return (_idx == _ag->GetSize());
}

Agrregate.h

//Aggregate.h
#pragma once

class Iterator;
typedef int Object;

class Aggregate {
public:
	virtual ~Aggregate();
	virtual Iterator* CreateIterator() = 0;
	virtual Object GetItem(int idx) = 0;
	virtual int GetSize() = 0;
protected:
	Aggregate();
private:
};

class ConcreteAggregate : public Aggregate {
public:
	enum{SIZE = 3};
	ConcreteAggregate();
	~ConcreteAggregate();
	Iterator* CreateIterator();
	Object GetItem(int idx);
	int GetSize();
protected:
private:
	Object _objs[SIZE];
};

Aggregate.cpp

//Agreggate.cpp
#include "Aggregate.h"
#include "Iterator.h"

#include <iostream>
using namespace::std;

Aggregate::Aggregate() {}
Aggregate::~Aggregate(){}

ConcreteAggregate::ConcreteAggregate() {
	for (int i = 0; i < SIZE; i++) {
		_objs[i] = i;
	}
}
ConcreteAggregate::~ConcreteAggregate() {}
Iterator* ConcreteAggregate::CreateIterator(){
	return new ConcreteIterator(this);
}
Object ConcreteAggregate::GetItem(int idx) {
	if (idx < this->GetSize()) {
		return _objs[idx];
	}
	else {
		return -1;
	}
}
int ConcreteAggregate::GetSize() {
	return SIZE;
}

main.cpp

//main.cpp
#pragma once

#include "Aggregate.h"
#include "Iterator.h"

#include <iostream>
using namespace::std;

int main(int argc, char* argv[]) {
	Aggregate* ag = new ConcreteAggregate();
	Iterator* it = new ConcreteIterator(ag);
	for (; !(it->IsDone()); it->Next()) {
		cout << it->CurrentItem() << endl;
	}
	return 0;
}