[工作中的设计模式]迭代子模式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
一.模式解析 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知 ...
随机推荐
- Tomcat基本入门知识及发布,虚拟访问及启动碰到的错误,虚拟目录,虚拟路径,各种Tomcat的配置
Tomcat容器入门介绍 转自javaresearch.com由timgball 整理 Tomcat是一个免费的开源Web服务器,最新版本是5.5.1,支持Servlet2.4,JSP2.0,非常适合 ...
- 探索ASP.NET MVC框架之路由系统
引言 对于ASP.NET MVC的路由系统相信大家肯定不陌生.今天我们就深入ASP.NET的框架内部来看一下路由系统到底是怎么通过我们给出的地址(例如:/Home/Index)解析出Controlle ...
- Daily Build
Daily Build 是一件非常有意义的事情,也是敏捷开发中关于 “持续集成” 的一个实践.Daily Build 对于开发来说有如下好处: 保证了每次 check in 的代码可用,不会造成整个工 ...
- 子类可以有跟父类中同名的方法,但是会重写父类中的方法,甚至是root class中的方法
/* 子类可以重写父类中的方法,甚至是root class中的方法,比如NSObeject 的new方法,但是后提示警告如下 Method is expected to return an insta ...
- storyboard连线容易出现的问题
- 连接的方法代码被删掉,但是连线没有去掉 - 可能会出现方法找不到错误 - unrecognized selector sent to instance- 连接的属性代码被删掉,但是连线没有去掉 - ...
- [linux]Socket编程的头文件
socket编程中需要用到的头文件 sys/types.h:数据类型定义 sys/socket.h:提供socket函数及数据结构 netinet/in.h:定义数据结构sockaddr_in arp ...
- 如何取消 DiscuzX 帖子被系统自动隐?
设置路径: 全局 -> 站点功能 -> 帖子阅读 -> 启用隐藏水帖,选择“否”
- URL转义
在处理一些url的时候常常会出现一些让人意想不到的情况,比如:当图片的链接中有空格的时候, this.src='http://img.cits-sh.com/UploadImgs/beihaidao2 ...
- ASP.NET Core--条件处理程序中的依赖注入
翻译如下: 在配置期间(使用依赖注入),授权处理程序必须在服务集合中注册. 假设您有一个在授权处理程序中要解析规则的仓储库,并且该仓储库已在服务集合中注册. 授权将在构造函数还原并注入. 例如,如果你 ...
- 摄像头视频捕捉(简单通用--通过IsampleGrabberCB实现)
前言 DirectShow是微软公司提供的一套在Windows平台上进行流媒体处理的开发包,与DirectX开发包一起发布.DirectShow为多媒体流的捕捉和回放提供了强有力的支持.用Direct ...