提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
访问一个聚合对象的内容而无需暴露它的内部表示。
支持对聚合对象的多种遍历。
为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。
迭代器模式的构成
1 抽象迭代器(Iterator)角色:此抽象角色定义出遍历元素所需的接口
2 具体迭代器(ConcreteIterator)角色:此角色实现了Iterator接口,并保持迭代过程中游标的位置
3 聚集(Aggregate)角色:此抽象角色给出创建迭代器(Iterator)对象的接口
4 具体聚集(ConcreteAggregate)角色:实现了创建迭代器(Iterator)对象的接口,返回一个合适的具体迭代器实例
5 客户端(Client)角色:持有对聚集及其迭代子对象的引用,调用迭代子对象的迭代接口,也有可能通过迭代器操作聚集元素的增加和删除
看下UML
首先,为什么使用迭代器模式,目的就是通过一个通用的迭代方法,隐藏stack,list,set以及数组中不同的遍历细节。也就是说,我不想让那些调用我的遍历容器的方法的人知道我到底是怎么一个一个的获取这些元素的(stack的pop,list的get,数组的array[i]),我只想让他知道他能 通过一个迭代器Iterator或者通过一个for each语句就能拿到我容器里面所有的元素。这样就能够最大化的隐藏实现细节,封装变化了。
先通过一个例子来一步步了解这其中的重要性吧。比方说,我要开发一个平台,这个平台会获取到京东的订单和淘宝的订单,然后把订单中的所有购买条目全部打印出来。
既然要打印订单中的所有条目,那么就得先知道这些条目,也就是订单项有哪些属性。
/**
* Project Name:TestProject
* File Name:Item.java
* Package Name:com.iterator
* Date:2017年12月13日下午7:42:59
* Copyright (c) 2017, lm All Rights Reserved.
*
*/
package com.iterator;
/**
* ClassName:Item <br/>
* Function: TODO ADD FUNCTION. <br/>
* Reason: TODO ADD REASON. <br/>
* Date: 2017年12月13日 下午7:42:59 <br/>
* @author lm
* @version
* @since JDK 1.8
* @see
*/
public class Item {
/**商品名称*/
private String name;
/**价格*/
private double price;
/**描述*/
private String desc;
/**数量*/
private int count;
public Item(String name, double price, String desc, int count) {
this.name = name;
this.price = price;
this.desc = desc;
this.count = count;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return "Item [name=" + name + ", price=" + price + ", desc=" + desc + ", count=" + count + "]";
}
}
知道了这个条目,然后我想看看京东和淘宝是如何存储这些条目的。于是我问了问刘强东和马云,得知京东是用集合List存储,因为方便,而淘宝是用数组存储,因为看起来更装逼。他们都不愿意修改存储的容器,因为改动太大。
这时, 如果用传统想法,ok,我拿到京东的List,然后通过for循环和list.get(i)获取里面的每个条目并打印。然后拿到淘宝的array,通过for循环和array[i]获取里面的条目并打印。是不是可以实现呢?确实可以,但是我发现这样的话,每个容器我都要实现一遍不同的打印方法。目前是两个倒还好,如果又来个谁谁谁,用链表来实现容器,那我是不是又要新加一个迭代链表的方法呢?我当然不会愿意,因为这样太麻烦了。于是乎,我有个想法,思路是这样的:
/**
* Project Name:TestProject
* File Name:Iterator.java
* Package Name:com.iterator
* Date:2017年12月13日下午7:50:36
* Copyright (c) 2017, lm All Rights Reserved.
*
*/
package com.iterator;
/**
* ClassName:Iterator <br/>
* Function: TODO ADD FUNCTION. <br/>
* Reason: TODO ADD REASON. <br/>
* Date: 2017年12月13日 下午7:50:36 <br/>
* @author lm
* @version
* @since JDK 1.8
* @see
*/
public interface Iterator<T> {
/**
* 是否还有下一个元素
* @return true 表示有,false 表示没有
* */
boolean hasNext();
/**
* 返回当前位置的元素并将位置移至下一位
* */
T next();
}
/**
* Project Name:TestProject
* File Name:ArrayIterator.java
* Package Name:com.iterator
* Date:2017年12月13日下午8:04:44
* Copyright (c) 2017, lm All Rights Reserved.
*
*/
package com.iterator;
/**
* ClassName:ArrayIterator <br/>
* Function: TODO ADD FUNCTION. <br/>
* Reason: TODO ADD REASON. <br/>
* Date: 2017年12月13日 下午8:04:44 <br/>
* @author lm
* @version
* @since JDK 1.8
* @see
*/
public class ArrayIterator<T> implements Iterator<T> {
private T[] list;
private int cursor = 0;
@Override
public boolean hasNext() {
return cursor != list.length;
}
@Override
public T next() {
T obj = null;
if(this.hasNext()){
obj = this.list[cursor++];
}
return obj;
}
public ArrayIterator(T[] list) {
super();
this.list = list;
}
}
/**
* Project Name:TestProject
* File Name:ConcreteIterator.java
* Package Name:com.iterator
* Date:2017年12月13日下午7:51:04
* Copyright (c) 2017, lm All Rights Reserved.
*
*/
package com.iterator;
import java.util.ArrayList;
import java.util.List;
/**
* ClassName:ConcreteIterator <br/>
* Function: TODO ADD FUNCTION. <br/>
* Reason: TODO ADD REASON. <br/>
* Date: 2017年12月13日 下午7:51:04 <br/>
* @author lm
* @version
* @since JDK 1.8
* @see
*/
public class ListIterator<T> implements Iterator<T> {
private List<T> list = new ArrayList<>();
private int cursor = 0;
public ListIterator(List<T> list) {
super();
this.list = list;
}
@Override
public boolean hasNext() {
return cursor != list.size();
}
@Override
public T next() {
T obj = null;
if(this.hasNext()){
obj = this.list.get(cursor++);
}
return obj;
}
}
/**
* Project Name:TestProject
* File Name:Aggregate.java
* Package Name:com.iterator
* Date:2017年12月13日下午7:53:58
* Copyright (c) 2017, lm All Rights Reserved.
*
*/
package com.iterator;
/**
* ClassName:Aggregate <br/>
* Function: TODO ADD FUNCTION. <br/>
* Reason: TODO ADD REASON. <br/>
* Date: 2017年12月13日 下午7:53:58 <br/>
* @author lm
* @version
* @since JDK 1.8
* @see
*/
public interface Aggregate<T> {
/**
* 添加一个元素
* @param obj 元素对象
* */
void add(T obj);
/**
* 移除一个元素
* @param obj 元素对象
* */
void remove(T obj);
/**
* 获取容器的迭代器
* @return 迭代器对象
* */
Iterator<T> iterator();
}
/**
* Project Name:TestProject
* File Name:JdOrder.java
* Package Name:com.iterator
* Date:2017年12月13日下午7:54:31
* Copyright (c) 2017, lm All Rights Reserved.
*
*/
package com.iterator;
import java.util.ArrayList;
import java.util.List;
/**
* ClassName:JdOrder <br/>
* Function: TODO ADD FUNCTION. <br/>
* Reason: TODO ADD REASON. <br/>
* Date: 2017年12月13日 下午7:54:31 <br/>
* @author lm
* @version
* @since JDK 1.8
* @see
*/
public class JdOrder implements Aggregate<Item> {
private List<Item> list = new ArrayList<>();
@Override
public void add(Item obj) {
list.add(obj);
}
@Override
public void remove(Item obj) {
list.remove(obj);
}
@Override
public Iterator<Item> iterator() {
return new ListIterator<Item>(list);
}
}
/**
* Project Name:TestProject
* File Name:TbOrder.java
* Package Name:com.iterator
* Date:2017年12月13日下午8:02:07
* Copyright (c) 2017, lm All Rights Reserved.
*
*/
package com.iterator;
/**
* ClassName:TbOrder <br/>
* Function: TODO ADD FUNCTION. <br/>
* Reason: TODO ADD REASON. <br/>
* Date: 2017年12月13日 下午8:02:07 <br/>
* @author lm
* @version
* @since JDK 1.8
* @see
*/
public class TbOrder implements Aggregate<Item> {
private int size=3;
private Item[] orders=new Item[size];
private int index=0;
@Override
public void add(Item obj) {
//如果超过数组大小,就扩容
if(index>=size-1){
resize();
}
orders[index++]=new Item("天猫1", 1111, "天猫活动1", 1);
}
@Override
public void remove(Item obj) {
}
@Override
public Iterator<Item> iterator() {
// TODO Auto-generated method stub
return new ArrayIterator<>(orders);
}
/**扩容*/
private void resize() {
size=size<<1;//移位运算符--相当于size=size*2
Item[] newItems=new Item[size];
//将原始数组内容拷贝到新数组中去
for(int i=0;i<orders.length;i++){
newItems[i]=orders[i];
}
orders=newItems;
}
}
/**
* Project Name:TestProject
* File Name:Clinet.java
* Package Name:com.iterator
* Date:2017年12月13日下午8:10:12
* Copyright (c) 2017, lm All Rights Reserved.
*
*/
package com.iterator;
/**
* ClassName:Clinet <br/>
* Function: TODO ADD FUNCTION. <br/>
* Reason: TODO ADD REASON. <br/>
* Date: 2017年12月13日 下午8:10:12 <br/>
* @author lm
* @version
* @since JDK 1.8
* @see
*/
public class Clinet {
public static void main(String[] args){
Item a =new Item("天猫1", 1111, "天猫活动1", 1);
Item b =new Item("天猫1", 1111, "天猫活动1", 1);
Item c =new Item("京东", 1111, "京东活动1", 1);
Item d =new Item("京东1", 1111, "京东活动1", 1);
JdOrder o = new JdOrder();
o.add(d);
o.add(c);
TbOrder t = new TbOrder();
t.add(a);
t.add(b);
Iterator it=o.iterator();
Iterator itt=t.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
while(itt.hasNext()){
System.out.println(itt.next());
}
}
}
Item [name=京东1, price=1111.0, desc=京东活动1, count=1]
Item [name=京东, price=1111.0, desc=京东活动1, count=1]
Item [name=天猫1, price=1111.0, desc=天猫活动1, count=1]
Item [name=天猫1, price=1111.0, desc=天猫活动1, count=1]