设计模式之 迭代器模式

迭代器模式(Iterator Pattern),提供了顺序访问集合中每个元素的功能,并且不用暴露其对象内部表示。

简单来说,就是实现一个迭代功能,迭代功能,每种编程语言都有,比如for循环就可以直接用,但是for循环有个问题就是,使用for循环,要明确知道被遍历的对象是什么,只有知道了类型,才能操作获取其中的对象。

如果是数组,那么就是下面这种:

int[] arrs = new int[]{1,2,3,4,5};
for(int i=0;i<=arrs.length; i++) {
    arrs[i]
    ...
}

如果是集合,那么遍历的方式,判断集合长度,就要变成:

for(int i=0;i<=list.size(); i++) {
    list.get(i)
    ...
}

这就是我们上面阐述的问题,我需要明确知道被遍历对象是什么。

并且像上面,内部的一组对象类型也要统一。

而使用迭代器,这些差异,将会被迭代器封装,不管是数组、ArrayList、LinkedList等等,最后调用迭代获取元素的方式是统一的,从表面看是没有差异的,这就是迭代器模式的优势。

我们来看一下演示代码:

1、新建自定义抽象迭代器

package com.itzhimei.study.design.iterator;

/**
 * www.itzhimei.com
 * 迭代器模式--自定义抽象迭代器
 */
public interface IMyIterator {

    boolean hasNext();

    Object next();
}

2、新建自定义实现具体迭代器

package com.itzhimei.study.design.iterator;

import java.util.ArrayList;

/**
 * www.itzhimei.com
 * 迭代器模式--自定义实现具体迭代器
 */
public class MyIterator implements IMyIterator {

    private ArrayList<Object> list;
    private int index = -1;

    public MyIterator(ArrayList<Object> list) {
        this.list = list;
    }

    /**
     * 判断是否还有元素
     * @return
     */
    @Override
    public boolean hasNext() {
        return this.list == null ? false: (index < list.size()-1);
    }

    /**
     * 获取元素
     * @return
     */
    @Override
    public Object next() {
        if(this.list != null && index < list.size()-1) {
            return this.list.get(++index);
        }
        return null;
    }
}

3、新建自定义抽象迭代器持有类

package com.itzhimei.study.design.iterator;

/**
 * www.itzhimei.com
 * 迭代器模式--自定义抽象迭代器持有类
 */
public interface IMyList {

    IMyIterator iterator();
}

4、新建自定义具体迭代器持有类

package com.itzhimei.study.design.iterator;

import java.util.ArrayList;

/**
 * www.itzhimei.com
 * 迭代器模式--自定义具体迭代器持有类
 */
public class MyList implements IMyList{

    ArrayList<Object> list;

    public MyList(ArrayList<Object> list) {
        this.list = list;
    }

    @Override
    public IMyIterator iterator() {
        return new MyIterator(this.list);
    }
}

5、新建用于迭代的Person类

package com.itzhimei.study.design.iterator;

/**
 * www.itzhimei.com
 * 迭代器模式--Person类用于测试
 */
public class Person {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

6、测试

package com.itzhimei.study.design.iterator;

import java.util.ArrayList;

/**
 * www.itzhimei.com
 * 测试
 */
public class Client {

    public static void main(String[] args) {

        Person p1 = new Person();
        p1.setName("张三");
        Person p2 = new Person();
        p2.setName("李四");
        Person p3 = new Person();
        p3.setName("王五");
        ArrayList ps = new ArrayList();
        ps.add(p1);
        ps.add(p2);
        ps.add(p3);

        IMyList list = new MyList(ps);
        IMyIterator iterator = list.iterator();

        while(iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println("迭代打印Person Name:"+((Person)next).getName());
        }

    }
}

输出结果:

迭代打印Person Name:张三
迭代打印Person Name:李四
迭代打印Person Name:王五

类关系图:

总结:

迭代器的优势

1、迭代器不需要知道结合对象内部实现细节,就能够实现集合元素的遍历;

2、使用迭代器后,获取元素的方式,就不再是下标,而是通过通用方式,比如这里演示代码中的next()方法;你可能会说,你的next代码中也使用了下标获取元素才返回的,确实如此,这是因为视角不同,我们使用迭代器模式,好处在于将集合的迭代、元素获取,同某一个集合的具体迭代方式、使用方式解耦。

还是那句话,设计模式都是在特定的场景下,才能发挥巨大作用。