[工作中的设计模式]迭代子模式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
一.模式解析 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知 ...
随机推荐
- [C#] 图文解说调用WebServer实例
本文旨在实现如何在.NET环境下调用WebServer,以天气接口为例进行说明. WebServer地址:http://www.webxml.com.cn/WebServices/WeatherWeb ...
- <<< html编码中js和html编码不一致导致乱码
在html中,有时把编码设置成UTF-8之后,引入js,页面不会有乱码,但是有关js的东西会出现乱码, 大概问题就是js默认编码不是UTF-8, 解决办法:将js文件用记事本打开,在另存为,保存的时候 ...
- 我的SqlHelper类!
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...
- 如何同时打开两个excel
1. 打开一个excel1 2. 不要双击想要打开的excel2.右键excel应用的图标,选择excel2007. 3. 将excel2拖动到2所打开的新建excel中. 4. over.
- 14个技巧助你适配 iOS10
1.Notification(通知) 自从 Notification 被引入之后,苹果就不断的更新优化,但这些更新优化只是小打小闹,直至现在iOS 10开始真正的进行大改重构,这让开发者也体会到 Us ...
- 关于 Word Splitting 和 IFS 的三个细节
在 Bash manual 里叫 Word Splitting,在 Posix 规范里叫 Field Splitting,这两者指的是同一个东西,我把它翻译成“分词”,下面我就说三点很多人都忽略掉(或 ...
- 简单的方向传感器SimpleOrientationSensor
SimpleOrientationSensor是一个简单的方向传感器.能够识别手机如下表的6种方向信息: SimpleOrientation枚举变量 方向 NotRotated 设备未旋转 Rotat ...
- spring mvc+mybatis+sql server简单配置
context.xml配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&qu ...
- 【阿里李战】解剖JavaScript中的 null 和 undefined
在JavaScript开发中,被人问到:null与undefined到底有啥区别? 一时间不好回答,特别是undefined,因为这涉及到undefined的实现原理.于是,细想之后,写下本文,请各位 ...
- 2.2WebApi路由在Action上
这篇文章描述 ASP.NET Web API 如何将 HTTP 请求路由到特定的操作在控制器上. 有关路由的高级别概述,请参见ASP.NET Web API 的路由. 本文着眼于路由进程的详细信息.如 ...