C++ 設計模式之迭代器模式
簡介
1、迭代器模式(Iterator)是一種行為型設計模式,它允許我們順序訪問一個聚合對象中的各個元素,而又不暴露該對象的內部表示。迭代器模式提供了一種方法來遍歷容器(容器對象,如列表、集合等)中的元素,而不需要了解容器底層的表示。
2、迭代器模式 (Iterator)應用場景包括但不限于:
2.1、當你的集合具有復雜的數據結構,并且你希望對客戶代碼隱藏其復雜性時。
2.2、當你需要一個遍歷的聚合對象,而且你希望有多種不同遍歷的方式時。
3、迭代器模式 (Iterator)的構成
3.1、迭代器接口(Iterator):定義訪問和遍歷元素的接口。
template<typename T>
class Iterator
{
public:virtual ~Iterator() {};virtual bool hasNext() const = 0;virtual T next() = 0;
};
3.2、具體迭代器(Concrete Iterator):實現迭代器接口,并跟蹤遍歷具體對象中的當前位置。
template<typename T>
class ConcreteAggregate
{
public:void add(T value);// 返回迭代器對象指針的嵌套類定義(具體迭代器)class IteratorImpl : public Iterator<T>{public:IteratorImpl(ConcreteAggregate& collection);T next();bool hasNext() const;private:ConcreteAggregate& collection;int current;};Iterator<T>* createIterator();
private:std::vector<T> data;
};
4、迭代器模式 (Iterator)的優點
4.1、支持不同的遍歷策略:可以自定義迭代器適應不同的數據結構和遍歷策略。
4.2、簡化集合接口:將遍歷邏輯從集合中抽離出來,集合本身的接口和實現都被簡化了。
4.3、同時在不同的集合上遍歷:一個集合可以有多個迭代器同時在不同位置進行遍歷。
4.4、同一抽象的多個實現:可以為不同的集合結構提供一個共同的迭代器接口。
5、迭代器模式 (Iterator)的缺點
5.1、可能不必要:對于一些簡單的集合操作,使用迭代器可能看起來是“過度設計”。
5.2、性能問題:創建額外的對象和調用方法可能會影響遍歷的性能。
簡單示例
1、定義
// 迭代器接口
template<typename T>
class Iterator
{
public:virtual ~Iterator() {};virtual bool hasNext() const = 0;virtual T next() = 0;
};// 具體集合
template<typename T>
class ConcreteAggregate
{
public:void add(T value);// 返回迭代器對象指針的嵌套類定義(具體迭代器)class IteratorImpl : public Iterator<T>{public:IteratorImpl(ConcreteAggregate& collection);T next();bool hasNext() const;private:ConcreteAggregate& collection;int current;};Iterator<T>* createIterator();
private:std::vector<T> data;
};
2、實現
template class ConcreteAggregate<int>; // 顯示實例化模板,裝載其他類型會編譯報錯,實際項目應將模板函數定義和實現放一起template<typename T>
void ConcreteAggregate<T>::add(T value)
{data.push_back(value);
}template<typename T>
Iterator<T>* ConcreteAggregate<T>::createIterator()
{return new IteratorImpl(*this);
}template<typename T>
ConcreteAggregate<T>::IteratorImpl::IteratorImpl(ConcreteAggregate& collection) : collection(collection), current(0)
{}template<typename T>
T ConcreteAggregate<T>::IteratorImpl::next()
{if (!hasNext()){throw std::out_of_range("Iterator out of range");}return collection.data[current++];
}template<typename T>
bool ConcreteAggregate<T>::IteratorImpl::hasNext() const
{return current < collection.data.size();
}
3、調用
ConcreteAggregate<int> collection;
collection.add(1);
collection.add(2);
collection.add(3);
collection.add(4);
auto it = collection.createIterator();
while (it->hasNext())
{std::cout << it->next() << std::endl;
}
delete it;