设计模式之迭代器模式

60 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第22天,点击查看活动详情

简介

迭代器大家应该都不陌生,记得之前学习struts、Jsp的时候就有一个s:iterator标签。今天给来个英文版的定义:

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation. ——《Design Patterns: Elements of Reusable Object-Oriented Software》

翻译过来就是:在不暴露聚合对象内部表现形式的情况下提供了一种顺序获取它内部元素的方式。英文翻译过来还是比较别扭,通俗来说就是这种模式用于顺序访问集合对象的元素,而不需要知道集合对象的底层表示是什么。

案例

我们将我们一天的工作内容来作为例子来写demo。我们一天的工作是啥呢?首先是听需求、然后做设计、做编码、最后修bug。那我们怎么来利用迭代器模式遍历一天的工作呢。

首先,定义一个抽象的任务类

public class Task {
    public Task(String name) {
        this.name = name;
    }
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

然后定义一个抽象的迭代器,一般情况下我们发现迭代器中一版必须含有2个方法,一个是判断是否是最后一个元素,一个是获取下个元素,所以抽象迭代器定义如下:

public interface TaskIterator {
    boolean hasNext();
    Task next();
}

然后我们定义一个实现迭代器,迭代器实现必须要有被迭代遍历的东西,所以有一个task的集合对象在里面,即

public class TaskIteratorImpl implements TaskIterator {
    private List<Task> taskList;
    private Integer current = 0;

    public TaskIteratorImpl(List<Task> taskList) {
        this.taskList = taskList;
    }
    @Override
    public boolean hasNext() {
        return current < taskList.size();
    }
    @Override
    public Task next() {
        Task task = taskList.get(current);
        current++ ;
        return task;
    }
}

接下来我们要定义集合对象了,定义一个抽象集合对象,有对对象操作的方法,然后还有一个获取迭代器的方法

public interface TaskCollection {
    void addTask(Task task);
    void minusTask(Task task);
    TaskIterator getIterator();
}

然后实现它:

public class TaskCollectionImpl implements TaskCollection {
    private List<Task> taskList = new ArrayList();
    @Override
    public void addTask(Task task) {
        taskList.add(task);
    }
    @Override
    public void minusTask(Task task) {
        taskList.remove(task);
    }
    @Override
    public TaskIterator getIterator() {
        return new TaskIteratorImpl(taskList);
    }
}

然后我们通过自定义的迭代器来遍历我们程序员一天的工作集合:

public class App {
    public static void main(String[] args) {
        TaskCollectionImpl taskCollection = new TaskCollectionImpl();
        taskCollection.addTask(new Task("听需求"));
        taskCollection.addTask(new Task("做设计"));
        taskCollection.addTask(new Task("做编码"));
        taskCollection.addTask(new Task("修bug"));
        for(TaskIterator iterator = taskCollection.getIterator(); iterator.hasNext();) {
            System.out.println(iterator.next().getName());
        }
    }
}

在我们的测试类中我们通过for循环加一个迭代器实现了对对象集合的遍历,专门抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。

总结

使用迭代器,由于我们引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足 “开闭原则” 的要求。但是还是那样,设计模式增加了不少的类,增加了维护和理解的难度。