“数据结构”模式之迭代器(Iterator)模式
常常有一些组件在内部具有特定的数据结构,如果让客户程序依赖这些特定的数据结构,将极大地破坏组件的复用。这时候,将这些特定数据结构封装在内部,在外部提供统一的接口,来实现与特定数据结构无关的访问,是一种行之有效的解决方案。
典型模式:
- Composite
- Iterator
- Chain of Resposibility
1 模式动机
在软件构建过程中,集合对象内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构(比如树、堆、栈等等)的同时,可以让外部客户代码透明地访问其中包含的元素;同时这种“透明遍历"也为“同一种算法在多种集合对象上进行操作”提供了可能。
2 模式定义
提供—种方法顺序访问一个聚合对象中的各个元素,而又不暴露(稳定)该对象的内部表示。
3 模式结构
4 代码示例
/** * Iterator Design Pattern * * Intent: Lets you traverse elements of a collection without exposing its * underlying representation (list, stack, tree, etc.). */ #include <iostream> #include <string> #include <vector> /** * C++ has its own implementation of iterator that works with a different * generics containers defined by the standard library. */ template <typename T, typename U> class Iterator { public: typedef typename std::vector<T>::iterator iter_type; Iterator(U *p_data, bool reverse = false) : m_p_data_(p_data) { m_it_ = m_p_data_->m_data_.begin(); } void First() { m_it_ = m_p_data_->m_data_.begin(); } void Next() { m_it_++; } bool IsDone() { return (m_it_ == m_p_data_->m_data_.end()); } iter_type Current() { return m_it_; } private: U *m_p_data_; iter_type m_it_; }; /** * Generic Collections/Containers provides one or several methods for retrieving * fresh iterator instances, compatible with the collection class. */ template <class T> class Container { friend class Iterator<T, Container>; public: void Add(T a) { m_data_.push_back(a); } Iterator<T, Container> *CreateIterator() { return new Iterator<T, Container>(this); } private: std::vector<T> m_data_; }; class Data { public: Data(int a = 0) : m_data_(a) {} void set_data(int a) { m_data_ = a; } int data() { return m_data_; } private: int m_data_; }; /** * The client code may or may not know about the Concrete Iterator or Collection * classes, for this implementation the container is generic so you can used * with an int or with a custom class. */ void ClientCode() { std::cout << "________________Iterator with int______________________________________" << std::endl; Container<int> cont; for (int i = 0; i < 10; i++) { cont.Add(i); } Iterator<int, Container<int>> *it = cont.CreateIterator(); for (it->First(); !it->IsDone(); it->Next()) { std::cout << *it->Current() << std::endl; } Container<Data> cont2; Data a(100), b(1000), c(10000); cont2.Add(a); cont2.Add(b); cont2.Add(c); std::cout << "________________Iterator with custom Class______________________________" << std::endl; Iterator<Data, Container<Data>> *it2 = cont2.CreateIterator(); for (it2->First(); !it2->IsDone(); it2->Next()) { std::cout << it2->Current()->data() << std::endl; } delete it; delete it2; } int main() { ClientCode(); return 0; }
输出结果:
________________Iterator with int______________________________________ 0 1 2 3 4 5 6 7 8 9 ________________Iterator with custom Class______________________________ 100 1000 10000
参考:https://refactoringguru.cn/design-patterns/iterator