[工作中的设计模式]迭代子模式Iterator
一、模式解析
迭代子模式又叫游标(Cursor)模式,是对象的行为模式。迭代子模式可以顺序地访问一个聚集中的元素而不必暴露聚集的内部表象
1、迭代子模式一般用于对集合框架的访问,常用的集合框架为list,set,map在实现的时候均可以支持迭代子模式
2、迭代子模式使用同意接口Iterator来完成对象的迭代,一般接口需要实现如下功能:first,next,isDone,currentItem等遍历接口
3、常用的集合框架根据访问需要,可以使用数组,链表等数据结构进行实现,使用迭代子模式可以屏蔽掉数据结构遍历时候产生的差异
4、在java中对结合的增强for循环依赖于迭代子模式实现
二、应用场景
迭代子模式在实际工作中基本无需自己进行编写,因为使用太过频繁,已经被jdk底层进行实现,所以我们使用集合框架时候直接使用就可以了,在这里,我们需要模拟ArrayList的基本实现和迭代子模式的实现。
ArrayList的基本结构为:
1、list内可以存放多个相同类型的元素,
2、元素可以重复存放
3、在jdk底层采用数组进行模拟,当存放数据容量超出数组,会对数组进行扩容,自动增加一部分容量,扩容算法为:(this.elementData.length*3)/2+1
4、继承了Iterator,可以使用迭代器进行遍历
三、场景代码
1、Iterator接口,定义迭代方法
package iterator.example;
/**
* 定义迭代器的接口
* @author zjl
* @time 2016-2-3
*
*/
public interface Iterator<E> {
public E first();
public E next();
public boolean isDone();
public int currentItem();
}
2、定义list接口,为了简化处理,此处直接继承迭代器接口
package iterator.example;
public interface List<E> extends Iterator<E> {
public int size();
public boolean isEmpty();
public E remove(int index);
public int indexOf(E e);
void add(E e);
public E get(int index);
}
3、定义Arraylist,实现各方法
package iterator.example;
import java.util.Arrays;
public class ArrayList<E> implements List<E>{
//初始化一个数组,来保存对象
Object[] elementData;
private int size=0;
//迭代器游标
private int cursor=0;
//数组初始化
public ArrayList(int init){
elementData=new Object[init];
}
//默认构造类型,默认初始化10个元素
public ArrayList(){
this(10);
}
@Override
public int size() {
return this.size;
}
@Override
public boolean isEmpty() {
return this.size==0;
}
@Override
public void add(E e) {
//如果list长度等于数组长度,那么将数组扩大
ensureCapacity(this.size+1);
elementData[this.size++]=e;
}
@Override
public E remove(int index) {
RangeCheck(index);
//移除指定位置的元素
E e= (E) elementData[index];
for(;index<this.size;index++){
elementData[index]=elementData[index+1];
}
elementData[index--]=null;
return e;
}
@Override
public int indexOf(E e) {
// TODO Auto-generated method stub
return 0;
}
//判断是否超长,如果超长,则扩展数组
public void ensureCapacity(int minCapacity){
int oldCapacity=this.elementData.length;
if(minCapacity>oldCapacity){
int newLength=(this.elementData.length*3)/2+1;
Object[] oldDate=this.elementData;
this.elementData=Arrays.copyOf(elementData, newLength);
}
}
private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
}
@Override
public E first() {
return (E) elementData[0];
}
@Override
public E next() {
if(isDone()){
throw new IndexOutOfBoundsException("the list is done");
}
return (E) elementData[cursor++];
}
@Override
public boolean isDone() {
return cursor==size;
}
@Override
public int currentItem() {
// TODO Auto-generated method stub
return cursor;
}
@Override
public E get(int index) {
RangeCheck(index);
return (E) elementData[index];
}
}
4、编写客户端程序
package iterator.example;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("java");
list.add("c++");
list.add("python");
list.add("Object-c");
while(!list.isDone()){
System.out.println(list.next());
}
}
}
5、执行结果
java
c++
python
Object-c
四、解决差异问题
此时,虽然可以正常使用迭代器进行循环,但是很明显和jdk中的ArrayList迭代方式不一致,而且无法使用增强循环模式for..in,观察下jdk的实现,我们发现list并没有实现Iterator接口,而是使用了Iterable接口作为过渡,在Iterable中保存了Iterator的引用。
修改代码为List继承jdk的Iterable,注意,此处必须引用jdk的接口才能增强循环,修改ArrayList代码为,增加方法为:
@Override
public Iterator<E> iterator() { return new Iterator<E>() {
private int cursor=0;
@Override
public boolean hasNext(){
return cursor!=size;
} @Override
public E next() {
return (E) elementData[cursor++];
}
//仅仅为了遍历,此方法暂不实现
@Override
public void remove() { } };
}
此时客户端可以使用与原生一样的迭代方法
Iterator<String> it=list.iterator();
while(it.hasNext()){
System.out.println(it.next());
} for(String s:list){
System.out.println(s);
}
为什么不直接继承Iterator接口,反而使用过渡呢,原因大概如下:
针对集合进行迭代时候,需要使用游标标记当前迭代位置,如果多个位置同时对一个集合进行迭代的话,那么同时需要多个游标来标记当前已经迭代的位置,如果直接继承Iterator接口,那么游标必须保持在集合框架本身,必然造成迭代的冲突,所以使用Iterable,每次开始迭代时候,返回一个Iterator的实现方法,产生一个游标,这样多次迭代不会产生相互冲突。
[工作中的设计模式]迭代子模式Iterator的更多相关文章
- [设计模式]迭代子模式 Iterator
迭代子模式又叫做游标cursor模式,是对象的行为模式.迭代子模式可以顺序的访问一个聚集中的元素而不必暴露聚集的内部表象. 迭代子模式被广泛的应用在Java语言的API中的几个设计模式之一.在Java ...
- [工作中的设计模式]备忘录模式memento
一.模式解析 备忘录对象是一个用来存储另外一个对象内部状态的快照的对象.备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把 ...
- java设计模式----迭代子模式
顺序访问聚集中的对象,主要用于集合中.一是需要遍历的对象,即聚集对象,二是迭代器对象,用于对聚集对象进行遍历访问. 迭代子模式为遍历集合提供了统一的接口方法.从而使得客户端不需要知道聚集的内部结构就能 ...
- [工作中的设计模式]享元模式模式FlyWeight
一.模式解析 Flyweight在拳击比赛中指最轻量级,即“蝇量级”或“雨量级”,这里选择使用“享元模式”的意译,是因为这样更能反映模式的用意.享元模式是对象的结构模式.享元模式以共享的方式高效地支持 ...
- [工作中的设计模式]原型模式prototype
一.模式解析 提起prototype,最近看多了js相关的内容,第一印象首先是js的原型 var Person=function(name){ this.name=name; } Person.pro ...
- 设计模式 - 迭代模式(iterator pattern) Java 迭代器(Iterator) 详细解释
迭代模式(iterator pattern) Java 迭代器(Iterator) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考迭代器模式(ite ...
- [工作中的设计模式]解释器模式模式Interpreter
一.模式解析 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器.客户端可以使用这个解释器来解释这个语言中的句子. 以上是解释器模式的类图,事实上我 ...
- [工作中的设计模式]中介模式模式Mediator
一.模式解析 用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互. 中介模式又叫调停者模式,他有如下特点: 1.有多个系统或者对 ...
- [工作中的设计模式]责任链模式chain
一.模式解析 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知 ...
随机推荐
- Beta版本——用户试用与调研报告
1 引言 1.1 系统概述 毕设导师智能分配系统是一个用来简化传统手工匹配繁琐操作的系统.本系统将学生报志愿.系负责人收集整理数据.相关人员进行手工分配.反馈选择结果等繁琐的操作转移到线上.把毕设 ...
- Node.js process 模块常用属性和方法
Node.js是常用的Javascript运行环境,本文和大家发分享的主要是Node.js中process 模块的常用属性和方法,希望通过本文的分享,对大家学习Node.js http://www.m ...
- [Unity] Shader - CG语言 流程控制语句
CG语言中: 不支持 switch 语句(可以写,但不能很好的执行.) 循环语句中, 循环次数不能大于 1024 ,否则会报错. If...ELSE 条件判断语句: if (true) { } els ...
- JSONP 理解 和 实例 讲解
1.什么是jsonp 1.1 同源策略 浏览器同源策略的限制,XmlHttpRequest只允许请求当前源(相同域名.协议.端口)的资源. -1)jsonp只支持get请求 -2)不受同源策略限制 , ...
- BerkeleyDB库简介
BerkeleyDB库简介 BerkeleyDB(简称为BDB)是一种以key-value为结构的嵌入式数据库引擎: 嵌入式:bdb提供了一系列应用程序接口(API),调用这些接口很简单,应用程序和b ...
- Activity初接触
Activity中TextView的文字显示Hello Android: 1.直接显示:<TextView android:text="Hello Android" /> ...
- spring mvc统一异常处理(@ControllerAdvice + @ExceptionHandler)
spring 封装了非常强大的异常处理机制.本文选取@ControllerAdvice + @ExceptionHandler 这种零配置(全注解),作为异常处理解决方案! @ControllerAd ...
- Android 网络编程
HttpClient 发送get请求 创建一个客户端对象 HttpClient client = new DefaultHttpClient(); 创建一个get请求对象 HttpGet hg = n ...
- PHP中global与$GLOBALS['']的区别
+++ 探讨(一)+++++++++++++++++++++++++++++++++++++++ 很多人都认为global和$GLOBALS[]只是写法上面的差别,其实不然. 根据官方的解释是 $GL ...
- JAVA解析XML的四种方法
XML文件:test.xml <?xml version="1.0" encoding="UTF-8"?> <employees> &l ...