迭代器模式

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

提供一种不公示其底层细节(结构)的情况下能顺序访问聚合对象元素的方法。

其实在java体系中,jdk已经引入了迭代器接口以及对于的容器接口等。就拿迭代器中的角色,在java中找出其对应的类。

具体角色

(1)迭代器角色(Iterator):定义遍历元素所需要的方法,一般来说会有这么三个方法:取得下一个元素的方法next(),判断是否遍历结束的方法hasNext()),移出当前对象的方法remove(),

(2)具体迭代器角色(Concrete Iterator):实现迭代器接口中定义的方法,完成集合的迭代。

(3)容器角色(Aggregate): 一般是一个接口,提供一个iterator()方法,例如java中的Collection接口,List接口,Set接口等

(4)具体容器角色(ConcreteAggregate):就是抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkList,Set接口的哈希列表的实现HashSet等。

单独举出ArrayList的角色,

迭代器角色对应java中的java.lang.Iterator,这个迭代器是java容器公用的。

容器角色对应java.lang.Iterable,其还有Iterator iterator()方法获取迭代器。

具体迭代器角色对应java.lang.ArrayList.Itr,实现了对应的hasNext、next、remove方法。

具体容器角色那就是java.lang.ArrayList了,实现iterator方法返回Itr具体迭代器,用游标形式实现。

再看看UML类

项目实例

源码在Github

项目中很简单的实现了一个容器和迭代器。大致参考了ArrayList实现,但是是简洁版本,去除很多无关以及性能上的东西,只保留最基本的迭代器元素。

@Slf4j
public class Application { public static void main(String[] args) {
Aggregate<Integer> aggregate = new ConcreteAggregate<>();
aggregate.add(1);
aggregate.add(2);
aggregate.add(3);
aggregate.add(4); Iterator<Integer> iterator = aggregate.iterator();
while (iterator.hasNext()) {
log.info("循环数据{}", iterator.next());
}
}
}

执行结果如下

简单的迭代器定义

public interface Iterator<E> {

    boolean hasNext();

    E next();

}

简单容器定义

public interface Aggregate<T> {

    Iterator<T> iterator();

    void add(T t);

}

具体容器和具体的迭代器定义

public class ConcreteAggregate<E> implements Aggregate<E> {

    private Object[] elements;

    private int size = 0;

    public ConcreteAggregate() {
elements = new Object[16];
} public int getSize() {
return size;
} public void add(E e) {
elements[size++] = e;
} @Override
public Iterator<E> iterator() {
return new ConcreteIterator<E>();
} private class ConcreteIterator<E> implements Iterator<E> { int cursor; @Override
public boolean hasNext() {
return cursor != size;
} @Override
public E next() {
if (cursor >= size) {
return null;
}
return (E) elements[cursor++];
} }
}

具体容器中用数组来作为容器来存储元素,而且最简单的容器,固定了大小,并没有实现扩容的算法等等,只是一个简单的样例,但是大部分上,都是直接使用java带有的迭代器。

优点

  • 简化了遍历方式,对于对象集合的遍历,还是比较麻烦的,对于数组或者有序列表,我们尚可以通过游标来取得,但用户需要在对集合了解很清楚的前提下,自行遍历对象,但是对于hash表来说,用户遍历起来就比较麻烦了。而引入了迭代器方法后,用户用起来就简单的多了。
  • 可以提供多种遍历方式,比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器,用户用起来只需要得到我们实现好的迭代器,就可以方便的对集合进行遍历了。
  • 封装性良好,用户只需要得到迭代器就可以遍历,而对于遍历算法则不用去关心。

缺点

由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐,大家可能都有感觉,像ArrayList,我们宁可愿意使用for循环和get方法来遍历集合。

总结

迭代器模式是与集合共生共死的,一般来说,我们只要实现一个集合,就需要同时提供这个集合的迭代器,就像java中的Collection,List、Set、Map等,这些集合都有自己的迭代器。假如我们要实现一个这样的新的容器,当然也需要引入迭代器模式,给我们的容器实现一个迭代器。

参考

wiki的迭代器模式

迭代器模式|菜鸟教程

Java设计模式系列之迭代器模式

欢迎关注我的微信公众号

折腾Java设计模式之迭代器模式的更多相关文章

  1. 折腾Java设计模式之建造者模式

    博文原址:折腾Java设计模式之建造者模式 建造者模式 Separate the construction of a complex object from its representation, a ...

  2. 折腾Java设计模式之备忘录模式

    原文地址:折腾Java设计模式之备忘录模式 备忘录模式 Without violating encapsulation, capture and externalize an object's int ...

  3. 折腾Java设计模式之状态模式

    原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...

  4. 折腾Java设计模式之模板方法模式

    博客原文地址:折腾Java设计模式之模板方法模式 模板方法模式 Define the skeleton of an algorithm in an operation, deferring some ...

  5. 折腾Java设计模式之访问者模式

    博客原文地址:折腾Java设计模式之访问者模式 访问者模式 Represent an operation to be performed on the elements of an object st ...

  6. 折腾Java设计模式之命令模式

    博客原文地址 折腾Java设计模式之命令模式 命令模式 wiki上的描述 Encapsulate a request as an object, thereby allowing for the pa ...

  7. 16.java设计模式之迭代器模式

    基本需求: 展示一个学校的结构,比如一个学校下面有多个学院,学院下面有多个系,对其节点主要是遍历,与组合模式略有不同 传统方案: 学校<-学院<-系 依次继承 这种方式,在一个页面中展示出 ...

  8. 简单的了解下Java设计模式:迭代器模式(转载)

    迭代器模式定义 迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示. Java 开发过程中遍历是常用的.如下边程序: for(int i =0 ; ...

  9. java设计模式之迭代器模式

    一.迭代器模式简介 迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 迭代器模式让我们能游走于聚合内的每一个元素,而又不暴露内部的表示.把游走的任务放在迭代器上,而不是 ...

随机推荐

  1. 目前比较流行的Python量化开源框架汇总(交易+风险分析工具)

     注:点击框架名称通往Github talib talib的简称是Technical Analysis Library,主要功能是计算行情数据的技术分析指标 numpy 介绍:一个用python实现的 ...

  2. 生产环境一键创建kafka集群

    前段时间公司的一个kafka集群出现了故障,由于之前准备不足,当时处理的比较慌乱.如:由于kafka的集群里topic数量较多,并且每个topic的分区数量和副本数量都不是一样的,如果按部就班的一个一 ...

  3. 手写DotNet Core 认证授权代码

    在普通的MVC项目中 我们普遍的使用Cookie来作为认证授权方式,使用简单.登录成功后将用户信息写入Cookie:但当我们做WebApi的时候显然Cookie这种方式就有点不适用了. 在dotnet ...

  4. Redis缓存穿透、缓存雪崩和缓存击穿理解

    1.缓存穿透(不存在的商品访问数据造成压力) 缓存穿透,是指查询一个数据库一定不存在的数据.正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并 ...

  5. 堪称神器的Chrome插件

    前言 相信很多人都在使用 Chrome 浏览器,其流畅的浏览体验得到了不少用户的偏爱,但流畅只是一方面, Chrome 最大的优势还是其支持众多强大好用的扩展程序(Extensions).最近为了更好 ...

  6. 从零开始学TensorFlow

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 最近在学习TensorFlow的相关知识,了解了Te ...

  7. Http通讯Util

    目录 HttpUtil类 HttpUtil类 import java.io.BufferedReader; import java.io.IOException; import java.io.Inp ...

  8. vue项目,axios请求图片接口,接口返回的是文件流的形式,如何转换成图片?

    axios .get('/captcha', { params: param, responseType: 'arraybuffer' }) .then(response => { return ...

  9. mysql 服务【安装】【启动】【停止】【卸载】【重置密码】

    windows安装:一.一机安装多个服务时,重复步骤,修改服务名即可: 1.mysqld install mysql_12336 --defaults-file="MYSQL_HOME\my ...

  10. Tomcat设置HTTPS访问

    根据查阅,选择了最方便的一种方法. 简单来说有两步,1:新生成一个密钥库keystore 2:配置 Tomcat 以使用该 keystore 文件.此时https可以访问,但会有证书不信任问题,介意的 ...