设计模式 18 迭代器模式 Iterator Pattern


设计模式 18 迭代器模式 Iterator Pattern
1.定义

迭代器模式 (Iterator Pattern) 是一种行为型设计模式,它提供了一种访问集合元素的标准方法,而无需暴露集合的内部表示。

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

核心思想来自将遍历集合的逻辑从集合本身中分离出来,封装到一个独立的迭代器对象中。
迭代器对象负责维护遍历的当前位置,并提供访问下一个元素的方法。

想象一个书架,上面摆满了书籍。如果你想阅读这些书籍,你可以选择不同的方式:

  • 直接访问: 你直接走到书架前,从最左边开始一本一本地拿书阅读。
  • 使用书签: 你用书签标记当前阅读的位置,下次阅读时直接从书签处开始。
2.内涵

迭代器模式就像使用书签一样,它提供了一种间接访问集合元素的方式:

迭代器对象: 就像书签,它记录了当前访问的位置。

  • next() 方法: 就像翻到下一页,它返回下一个元素。
  • hasNext() 方法: 就像判断是否有下一页,它判断是否还有下一个元素。
3.案例分析
/
  Iterator Design Pattern

 /

include <iostream>
include <string>
include <vector>


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_;
};

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_;
};


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;
}

上述代码 uml 类图如下


4.注意事项


     迭代器模式 Iterator Pattern 使用时需要注意什么?

    使用迭代器模式时,需要注意以下几点:

    1. 迭代器状态的维护:

     迭代器对象需要维护当前遍历的位置,确保每次调用 `next()` 方法都能返回下一个元素。
     迭代器对象需要处理遍历结束的情况,例如在 `hasNext()` 方法中返回 `false`,或在 `next()` 方法中抛出异常。

    2. 迭代器的类型:

     迭代器可以是内部迭代器,也称为迭代器方法,它将遍历逻辑封装在集合类内部,例如 Java 中的 `forEach` 方法。
     迭代器可以是外部迭代器,它是一个独立的类,负责遍历集合,例如 Java 中的 `Iterator` 接口。

    3. 迭代器的可复用性:

     迭代器对象通常是不可复用的,因为它们维护了遍历状态。
     如果需要多次遍历同一个集合,需要创建新的迭代器对象。

    4. 迭代器的并发访问:

     如果多个线程同时访问同一个迭代器对象,可能会导致数据不一致或异常。
     在并发环境中使用迭代器时,需要进行同步处理,例如使用锁机制来保护迭代器对象。

    5. 迭代器的性能:

     迭代器的性能取决于集合的类型和迭代器的实现方式。
     对于一些集合类型,例如链表,迭代器可能比直接访问元素效率低。

    6. 迭代器的灵活性:

     迭代器模式可以提供灵活的遍历方式,例如正序、逆序、随机访问等。
     可以根据需要自定义迭代器,实现不同的遍历逻辑。

    总结:

    迭代器模式是一种强大的设计模式,它可以简化对集合的遍历操作,并提供灵活的遍历方式。在使用迭代器模式时,需要关注迭代器状态的维护、类型、可复用性、并发访问和性能等方面,以确保代码的正确性和效率。

5.最佳实践


在使用迭代器模式时,除了前面提到的需要注意的地方,还需要遵循以下经验:

1. 明确迭代器职责

迭代器应该只负责遍历集合,不应该包含其他操作,例如修改集合元素。
如果需要修改集合元素,应该使用专门的方法,而不是通过迭代器来实现。


2. 保持迭代器简单

迭代器应该尽可能简单易懂,避免过度设计。
迭代器应该只包含必要的操作,例如 hasNext()、next() 等。


3. 考虑迭代器的性能

如果需要频繁遍历集合,应该选择性能较高的迭代器实现。
对于一些特殊类型的集合,例如链表,可能需要使用自定义迭代器来提高性能。


4. 避免迭代器中的副作用

迭代器不应该修改集合的状态,例如添加或删除元素。
如果需要修改集合,应该使用专门的方法,而不是通过迭代器来实现。


5. 使用迭代器模式的最佳实践

优先使用语言提供的内置迭代器,例如 Java 中的 Iterator 接口。
如果需要自定义迭代器,应该遵循迭代器模式的规范,并提供必要的操作。
避免在迭代器中使用 break 或 continue 语句,因为它们会破坏迭代器的正常逻辑。


6. 迭代器与并发

在并发环境中使用迭代器时,需要格外小心,因为多个线程可能会同时访问同一个迭代器对象。
如果需要在并发环境中使用迭代器,应该使用线程安全的迭代器实现,例如 Java 中的 ConcurrentIterator 接口。

6.总结

        迭代器模式是一种非常实用的设计模式,它可以帮助我们简化对集合的遍历操作,并提高代码的可读性和可维护性。在使用迭代器模式时,遵循以上经验可以帮助我们写出更加健壮和高效的代码。

7.行为模式汇总图

  • 24
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值