设计模式(4)--对象行为(4)--迭代器

1. 意图

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

2. 四种角色

    抽象集合(Aggregate)、具体集合(Concrete Aggregate)、抽象迭代器(Iterator)、具体迭代器(Concrete Iterator)

3. 优点

    3.1 支持以不同的方式遍历一个聚合

    3.2 简化了聚合的接口

    3.3 在同一个聚合上可以有多个遍历

4. 缺点

    N/A

5. 相关模式

    5.1 迭代器常被应用到Composite这样的递归结构上。

    5.2 多态迭代器靠工厂方法来实例化适当的迭代器子类。

    5.3 迭代器内部存储一个memento,用来捕获一个迭代的状态。

6. 代码示意(C++)
#pragma once
#include <vector>
#include <string>
#include <iostream>
using namespace std;

class Employee
{
	string m_name;
public:
	Employee(const string& name) :m_name(name) {

	}
	void Print() const {
		cout << m_name << endl;
	}
};

template <class T> class Iterator;
template <class T> class ForwardIterator;

template <class T>
class Aggregate
{
	friend class ForwardIterator<T>;
public:
	virtual void Add(T data) = 0;
	virtual Iterator<T>* CreateIterator() const = 0;
private:
	virtual int Size() const = 0;
	virtual const T* Get(long pos) const = 0;
};

template <class T>
class ConcreteAggregate : public Aggregate<T>
{
	vector<T> m_vector;
	Iterator<T>* m_pIt;
public:
	ConcreteAggregate() :m_pIt(0) {
	}
	~ConcreteAggregate() {
		delete m_pIt;
	}	
	virtual void Add(T data) {
		m_vector.emplace_back(data);
	}
	//方法一:用户需负责删除
	virtual Iterator<T>* CreateIterator() const {
		return new ForwardIterator<T>(this);
	}
	//方法二:析构函数负责删除
	virtual Iterator<T>& GetIterator() {
		//先删除老的
		delete m_pIt;
		m_pIt = new ForwardIterator<T>(this);
		return *m_pIt;
	}
private:
	virtual int Size() const { return m_vector.size(); }
	virtual const T* Get(long pos) const { return &(m_vector[pos]); }
};

template <class T>
class Iterator
{
public:
	virtual void First() = 0;
	virtual void Next() = 0;
	virtual bool IsDone() const = 0;
	virtual const T* CurrentItem() const = 0;
protected:
	Iterator() {}
};

template <class T>
class ForwardIterator : public Iterator<T> {
public:
	ForwardIterator(const Aggregate<T>* pData);
	virtual void First();
	virtual void Next();
	virtual bool IsDone() const;
	virtual const T* CurrentItem() const;
private:
	const Aggregate<T>* m_pData;
	long m_current;

};
template<class T>
ForwardIterator<T>::ForwardIterator(const Aggregate<T>* pData) :m_pData(pData), m_current(0)
{
}

template<class T>
void ForwardIterator<T>::First() {
	m_current = 0;
}

template<class T>
void ForwardIterator<T>::Next() {
	++m_current;
}

template<class T>
bool ForwardIterator<T>::IsDone() const {
	return m_current >= m_pData->Size();
}

template<class T>
const T* ForwardIterator<T>::CurrentItem() const {
	if (IsDone()) {
		return 0;
	}
	return m_pData->Get(m_current);
}
#include "Iterator.h"
int main() {
	//方法一
	Aggregate<Employee>* pAggregate = new ConcreteAggregate<Employee>();
	pAggregate->Add(Employee("张三"));
	pAggregate->Add(Employee("李四"));

	Iterator<Employee>* pIt = pAggregate->CreateIterator();
	for (pIt->First(); !pIt->IsDone(); pIt->Next()) {
		pIt->CurrentItem()->Print();
	}
	cout << endl;
	delete pIt;
	delete pAggregate;

	//方法二
	ConcreteAggregate<Employee> aggregate;
	aggregate.Add(Employee("王五"));
	aggregate.Add(Employee("赵六"));

	Iterator<Employee> &it = aggregate.GetIterator();
	for (it.First(); !it.IsDone(); it.Next()) {
		it.CurrentItem()->Print();
	}

	return 0;
}

运行结果:

6.1 可以很容易实现Iterator的子类以支持不同的遍历方式(3.1)

6.2 使用方法一,可以得到多个迭代器,但用户需要负责删除迭代器指针(3.3);

       而方法二则不需要用户删除指针(也可用代理类得到相同效果) 。

相关推荐

  1. 设计模式行为设计模式——模式

    2023-12-27 06:54:05       44 阅读
  2. GO设计模式——18、模式行为型)

    2023-12-27 06:54:05       65 阅读
  3. 设计模式(014)行为型之模式

    2023-12-27 06:54:05       31 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-27 06:54:05       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-27 06:54:05       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-27 06:54:05       82 阅读
  4. Python语言-面向对象

    2023-12-27 06:54:05       91 阅读

热门阅读

  1. SimLM: Can Language Models Infer Parameters of Physical Systems?

    2023-12-27 06:54:05       53 阅读
  2. Go语言Web框架Gin常见用法

    2023-12-27 06:54:05       47 阅读
  3. gin实现登录逻辑,包含cookie,session

    2023-12-27 06:54:05       48 阅读
  4. 手写一个vuex?

    2023-12-27 06:54:05       56 阅读
  5. 【Springboot】解决 MacOS M1 上 Netty 的 DNS 解析错误

    2023-12-27 06:54:05       63 阅读