一、模式介绍
迭代器模式又名游标模式,它使得一个集合对象可以在不暴露其内部表示的情况下被客户访问其包含对象,那么它是怎么做到的呢?它是通过实现了一组接口而做到的,而这组接口是开放给客户的,客户端只需使用该接口而无需知晓其实现的细节,因为封装的特性外界无法得知集合内部的表示那么实现集合迭代的具体细节就需要结合本身来完成。
根据迭代器的思想,我们完全可以隐藏更多的内部表示开放更多接口等形式给用户访问而不仅仅是开放遍历接口,迭代器模式的思想就是隐藏内部细节依旧对外提供服务。在java中这种使用方式真是太多了,简单的如ArrayList/HashMap/Queue等,都是以内部类的形式返回给用户一个Iterator接口供用户是使用,用户通过访问接口定义的方法就可以知晓其内部表示而不直接访问,因为可能由于安全或编译器不确定性等因素导致的无法直接访问。
jdk这种设计迭代器的思想值得学习。
二、原理图
三、示例代码
import java.util.*;
interface MyContainer {
void add(Object o);
void remove(Object o);
/**
* 获取一个可以遍历内部对象的接口,
* 这样,客户端可不必知晓内部是数组还是HashSet !!!
*/
MyIterator getIterator();
}
/**
* 开放给客户的遍历接口,已经隐藏了容器的内部实现
*/
interface MyIterator {
boolean hasNext();
Object next();
}
// 数组 实现的 集合
class ArrayMyContainer implements MyContainer {
int total;
Object[] os;
public ArrayMyContainer(int total) {
this.total = total;
this.os = new Object[total];
}
@Override
public void add(Object o) {
for (int i = 0; i < total; i++) {
if (os[i] == null) {
os[i] = o;
break;
}
}
}
@Override
public void remove(Object o) {
for (int i = 0; i < total; i++) {
if (os[i] != null && os[i].equals(o)) {
os[i] = null;
break;
}
}
}
@Override
public MyIterator getIterator() {
return new InternalIterator();
}
private class InternalIterator implements MyIterator {
int currentIndex = -1;
int temp;
@Override
public boolean hasNext() {
for (int i = (currentIndex + 1); i < total; i++) {
if (os[i] != null) {
temp = i;
return true;
}
}
return false;
}
@Override
public Object next() {
currentIndex = temp;
return os[currentIndex];
}
}
}
// HashSet 实现的 集合
class HashSetContainer implements MyContainer {
Set os = new HashSet();
@Override
public void add(Object o) {
os.add(o);
}
@Override
public void remove(Object o) {
os.remove(o);
}
@Override
public MyIterator getIterator() {
return new JDKIteratorAdapter();//返回一个JDK的适配器,用作迭代器,也可以隐藏内部的 HashSet 实现 !!!
}
/**
* 使用:JDK内置的迭代器
* 使用适配器模式,让“JDK内置的迭代器”可以适配到自己的迭代器接口
* Note:命名方式,如果是JDK要做适配器,就是:JDKxxAdapter
*/
class JDKIteratorAdapter implements MyIterator {
Iterator iterator;
public JDKIteratorAdapter() {
iterator = os.iterator();
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Object next() {
return iterator.next();
}
}
}
public class T {
public static void main(String[] args) {
MyContainer container = new ArrayMyContainer(100);
// container = new HashSetContainer();// 切换容器
// 客户不用知晓 MyContainer 内部实现就可以对其进行遍历,也可以类比隐藏其它操作!!!
for (int i = 0; i < 5; i++) {
container.add("对象" + i);
}
container.remove("对象2");//删除一个元素
container.remove("对象3");//删除一个元素
MyIterator myIterator = container.getIterator();//获取 遍历用的:迭代器!!
while (myIterator.hasNext()) {
Object next = myIterator.next();
System.out.println(next);
}
}
}
输出:
对象0
对象1
对象4