第十四章、迭代器模式

迭代器模式,又叫做游标模式。是行为型设计模式之中的一个。我们知道对容器对象的訪问必定会涉及遍历算法。我们能够将遍历的方法封装在容器中,或者不提供遍历方法,让使用容器的人自己去实现去吧。

这两种情况好像都能够解决这个问题。

然而在前一种情况。容器承受了过多的功能。它不仅要负责自己“容器”内的元素维护(加入、删除等等),并且还要提供遍历自身的接口;并且因为遍历状态保存的问题,不能对同一个容器对象同一时候进行多个遍历。另外一种方式倒是省事,却又将容器的内部细节暴露无遗。

正因于此,迭代器模式应运而生。在客户訪问类与容器体之间插入一个第三者–迭代器,非常好的攻克了上述弊端。

1.定义

提供一种方法顺序訪问一个容器对象中的各个元素,而又不须要暴露该对象的内部表示。

2.使用场景

遍历一个容器对象时。

3.简单实现

用书中的样例:小民和小辉分别在公司两个事业部,某天老板安排任务让他们俩统计一下各自部门的员工数据。

员工实体类:

public class Employee {

    private String name;// 姓名
private int age;// 年龄
private String sex;// 性别
private String position;// 职位 public Employee(String name, int age, String sex, String position) {
super();
this.name = name;
this.age = age;
this.sex = sex;
this.position = position;
} // 简化代码,省略setter和getter方法 @Override
public String toString() {
return "Employee{" + "name='" + name + '\'' + ", age=" + age + ", sex="
+ sex + ", position='" + position + '\'' + "}";
}
}

小辉部门:

public class CompanyHui {

private Employee[] array = new Employee[3];

    public CompanyHui(){
array[0] = new Employee("辉哥", 28, "男", "程序员");
array[1] = new Employee("小红", 23, "男", "程序员");
array[2] = new Employee("小辉", 25, "男", "程序员");
} public Employee[] getEmployees(){
return array;
}
}

小民部门:

public class CompanyMin {

    private List<Employee> list = new ArrayList<>();

    public CompanyMin(){
list.add(new Employee("小民", 26, "男", "程序员"));
list.add(new Employee("小芸", 22, "女", "測试"));
list.add(new Employee("小方", 18, "女", "測试"));
list.add(new Employee("可儿", 21, "女", "设计"));
list.add(new Employee("朗情", 19, "女", "设计")); //吐槽一下,为什么就小民一个男的,小辉部门全男的。 } public List<Employee> getEmployees(){
return list;
}
}

Boss查看:

public class Boss {
public static void main(String[] args) {
CompanyHui hui = new CompanyHui();
Employee[] huiList = hui.getEmployees();
for(int i = 0; i < huiList.length; i++){
System.out.println(huiList[i]);
} CompanyMin min = new CompanyMin();
List minList = min.getEmployees();
for(int i = 0; i < minList.size(); i++){
System.out.println(minList.get(i).toString());
}
}
}

结果:

Employee{name='辉哥', age=28, sex=男, position='程序员'}
Employee{name='小红', age=23, sex=男, position='程序员'}
Employee{name='小辉', age=25, sex=男, position='程序员'}
Employee{name='小民', age=26, sex=男, position='程序员'}
Employee{name='小芸', age=22, sex=女, position='測试'}
Employee{name='小方', age=18, sex=女, position='測试'}
Employee{name='可儿', age=21, sex=女, position='设计'}
Employee{name='朗情', age=19, sex=女, position='设计'}

这样看似也没有问题,可是假设有多个部门,每一个部门有各自的实现,那么我们就要在Boss类中添加一遍遍历逻辑,这样Boss类的功能会越来越多,同一时候暴露了内部细节。那么我们须要定义一个迭代器接口:

public interface Iterator {

    /**
* 是否还有下一个元素
*
* @return true表示有,false表示没有
*/
boolean hasNext(); /**
* 返回当前元素,并将位置移至下一位
*/
Object next();
}

小民的迭代器:

public class MinIterator implements Iterator{

    private List<Employee> list;
private int position; public MinIterator(List<Employee> list){
this.list = list;
} @Override
public boolean hasNext() {
return !(position > list.size() - 1 || list.get(position) == null);
} @Override
public Object next() {
Employee e = list.get(position);
position++;
return e;
} }

小辉的迭代器:

public class HuiIterator implements Iterator{

    private Employee[] array;
private int position; public HuiIterator(Employee[] array){
this.array = array;
} @Override
public boolean hasNext() {
return !(position > array.length - 1 || array[position] == null);
} @Override
public Object next() {
Employee e = array[position];
position++;
return e;
} }

定义容器类的接口

public interface Company {

    /**
* 返回一个迭代器对象
*
* @return 迭代器对象
*/
Iterator iterator(); }

改动一下之前的两个容器类:

public class CompanyHui implements Company{

    private Employee[] array = new Employee[3];

    public CompanyHui(){
array[0] = new Employee("辉哥", 28, "男", "程序员");
array[1] = new Employee("小红", 23, "男", "程序员");
array[2] = new Employee("小辉", 25, "男", "程序员");
} public Employee[] getEmployees(){
return array;
} @Override
public Iterator iterator() {
return new HuiIterator(array);
}
}
public class CompanyMin implements Company{

    private List<Employee> list = new ArrayList<>();

    public CompanyMin(){
list.add(new Employee("小民", 26, "男", "程序员"));
list.add(new Employee("小芸", 22, "女", "測试"));
list.add(new Employee("小方", 18, "女", "測试"));
list.add(new Employee("可儿", 21, "女", "设计"));
list.add(new Employee("朗情", 19, "女", "设计"));
} public List<Employee> getEmployees(){
return list;
} @Override
public Iterator iterator() {
return new MinIterator(list);
}
}

Boss查看:

public class Boss {
public static void main(String[] args) {
CompanyHui hui = new CompanyHui();
check(hui.iterator()); CompanyMin min = new CompanyMin();
check(min.iterator());
} private static void check(Iterator iterator){
while (iterator.hasNext()) {
System.out.println(iterator.next().toString());
}
}
}

结果不变,就不反复写了。

4.Android源代码中的模式实现

1.Cursor

当我们使用SQLiteDatabase的query方法查询数据库时。会返回一个Cursor游标对象,该游标的实质就是一个详细的迭代器,我们能够使用它来遍历数据库查询所得的结果集。

5.总结

迭代器模式发展至今。差点儿全部的高级语言都有对应的内置实现,对于开发人员而言,已经极少会自己去实现迭代器了,所以本章内容很多其它的是了解而非应用。

1.长处

(1)符合面向对象设计原则中的单一职责原则。

(2)支持对容器对象的多种遍历。弱化了容器类与遍历算法之间的关系。

2.缺点

(1)类文件的添加。

(3)会出现ConcurrentModificationException异常。

(2)遍历过程是一个单向且不可逆的遍历。

6.參考

● 深入浅出Java设计模式之迭代器模式

● ConcurrentModificationException异常

《Android源代码设计模式解析与实战》读书笔记(十四)的更多相关文章

  1. How tomcat works 读书笔记十四 服务器组件和服务组件

    之前的项目还是有些问题的,例如 1 只能有一个连接器,只能处理http请求,无法添加另外一个连接器用来处理https. 2 对容器的关闭只能是粗暴的关闭Bootstrap. 服务器组件 org.apa ...

  2. Java 读书笔记 (十四) Java 方法

    finalize() 方法 finalize() 用来清除回收对象.  //为什么要回收内存?怎样写可以避免内存过多占用?什么时候需要手动回收内存? protected void finalize() ...

  3. CSS揭秘读书笔记 (一)

    CSS揭秘读书笔记      (一) 一.半透明边框 要想实现半透明边框可以使用border: border: 10px  solid  hsla(0,0%,100%,.5); background: ...

  4. 《Linux内核设计与实现》第八周读书笔记——第四章 进程调度

    <Linux内核设计与实现>第八周读书笔记——第四章 进程调度 第4章 进程调度35 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间,进程调度程序可看做在可运行态进程之间分配 ...

  5. 《Linux内核设计与实现》 第八周读书笔记 第四章 进程调度

    20135307 张嘉琪 第八周读书笔记 第四章 进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间,进程调度程序可看做在可运行态进程之间分配有限的处理器时间资源的内核子系统.只有 ...

  6. 《Linux内核分析》读书笔记(四章)

    <Linux内核分析>读书笔记(四章) 标签(空格分隔): 20135328陈都 第四章 进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间,进程调度程序可看做在可运行 ...

  7. 《CSS世界》笔记二:盒模型四大家族

    上一篇:<CSS世界>笔记一:流/元素/尺寸下一篇:<CSS世界>笔记三:内联元素与对齐 写在前面 在读<CSS世界>第四章之前,粗浅的认为盒模型无非是margin ...

  8. python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例

    python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ...

  9. 《C++游戏开发》笔记十四 平滑过渡的战争迷雾(二) 实现:真正的迷雾来了

    本系列文章由七十一雾央编写,转载请注明出处.  http://blog.csdn.net/u011371356/article/details/9712321 作者:七十一雾央 新浪微博:http:/ ...

  10. Java多线程编程实战指南(核心篇)读书笔记(四)

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76690961冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...

随机推荐

  1. ueditor插入百度音乐无法播放-403 问题

    简单记录一下,其实403是因为百度音乐设置了禁止外部连接引用,因此 几乎所有的百度音乐播放都会提示403. 注意:预览页面(dialog/music/music.html)和实际插入页面(uedito ...

  2. WebService-axis2

    WebService框架有好多,常用的cxf,axis2等,axis2的配置过程相对简单,不用编写接口,在实现.只需要一个Service服务类即可.配置过程大致如下: 1,导入jar包(这里我是把ax ...

  3. main之前初始化流程

    main之前初始化流程 本文分别介绍Keil调用的ARMCC以及ARM-NONE-EABI-GCC两个编译器在main之前的操作: Keil MDK启动文件 总结一下MDK的启动流程: 1.系统初始化 ...

  4. C#PreviewKeyDown 与KeyDown 区别

    PreviewKeyDown:在焦点位于此控件上的情况下,当有按键动作时发生(在 KeyDown 事件之前发生). 小注: 某些按键,比如 Tab.Return.Esc 和箭头键,通常会被某些控件忽略 ...

  5. [转] 深刻理解Python中的元类(metaclass)

    非常详细的一篇深入讲解Python中metaclass的文章,感谢伯乐在线-bigship翻译及作者,转载收藏. 本文由 伯乐在线 - bigship 翻译.未经许可,禁止转载!英文出处:stacko ...

  6. 为什么ERP行业发展缓慢规模难扩大?

    题记:这个行业只会越来越好,但是能沉淀下来做事儿的企业越来越少,因为收益真的很漫长:能够真正进入这个行业难,出去也难... 经常在知乎上看到类似的问题:既然所有ERP系统都很烂,那有没有创业公司的空间 ...

  7. 操作系统学习笔记----进程/线程模型----Coursera课程笔记

    操作系统学习笔记----进程/线程模型----Coursera课程笔记 进程/线程模型 0. 概述 0.1 进程模型 多道程序设计 进程的概念.进程控制块 进程状态及转换.进程队列 进程控制----进 ...

  8. js笔记(制作一个简单的计数器)

    首先编写静态页中的按钮: <input  id="result" type="button" value="该程序已经运行了0秒!"/ ...

  9. 前端构建工具之争——Webpack vs Gulp 谁会被拍死在沙滩上

    .table tr>td:nth-child(1){width: 2em !important;padding-left: .6rem !important;padding-right: .6r ...

  10. cinder块存储 后端采用lvm、nfs安装配置

    #cinder块存储 后端采用lvm.nfs安装配置 openstack pike 安装 目录汇总 http://www.cnblogs.com/elvi/p/7613861.html #cinder ...