Iterator Patterns

GoF定义:在不暴露底层保存数据的结构情况下实现对集合对象的遍历(访问)

概念

迭代器经常被用来遍历容器(Container)中的元素

例子

现实世界:如果有两个公司,公司A使用链表保存职员信息,而公司B用大数组来保存职员信息,当两个公司合并,它们想用一种方式来查看员工信息。此时,这种统一的方式可以在不影响已有的结构下提供一个遍历职员信息的方法
代码世界:场景基本和现实世界例子差不多

展示

代码

public class IteratorPatternEx
{
    public static void main(String[] args)
    {
        System.out.println("***Iterator Pattern Demo***\n");
        Subject Sc_subject = new Science();
        Subject Ar_subjects = new Art();
        IIterator Sc_iterator = Sc_subject.createIterator();
        IIterator Ar_iterator = Ar_subjects.createIterator();
        System.out.println("\nScience subjects :");
        Print(Sc_iterator);
        System.out.println("\nArts subjects :");
        Print(Ar_iterator);
    }

    public static void Print(IIterator iterator)
    {
        while (!iterator.isDone())
        {
            System.out.println(iterator.next());
        }
    }
}

interface IIterator
{
    // 设置位置到第一个元素
    void first();
    // 得到下一个元素
    String next();
    // 是否到集合末尾
    boolean isDone();
    // 得到当前元素
    String currentItem();
}

interface Subject
{
     IIterator createIterator();
}

class Art implements Subject
{
    private String[] subjects;

    public Art()
    {
        this.subjects = new String[2];
        this.subjects[0] = "Bengali";
        this.subjects[1] = "English";
    }

    @Override
    public IIterator createIterator()
    {
        return new ArtIterator(this.subjects);
    }

    class ArtIterator implements IIterator
    {
        private String[] col;
        private int pos = 0;

        public ArtIterator(String[] col)
        {
            this.col = col;
        }


        @Override
        public void first()
        {
            this.pos = 0;
        }

        /**
         * 将指针位置向后移
         * @return 当前位置元素
         */
        @Override
        public String next()
        {
            return this.col[this.pos++];
        }

        @Override
        public boolean isDone()
        {
            return pos >= this.col.length;
        }

        @Override
        public String currentItem()
        {
            return this.col[this.pos];
        }
    }
}

class Science implements Subject
{
    private LinkedList<String> subjects;

    public Science()
    {
        subjects = new LinkedList<>();
        subjects.addLast("Maths");
        subjects.addLast("Comp. Sc.");
        subjects.addLast("Physics");
    }

    @Override
    public IIterator createIterator()
    {
        return new ScienceIterator(this.subjects);
    }

    class ScienceIterator implements IIterator
    {
        private LinkedList<String> col;
        private int pos = 0;

        public ScienceIterator(LinkedList<String> col)
        {
            this.col = col;
        }

        @Override
        public void first()
        {
            this.pos = 0;
        }

        @Override
        public String next()
        {
            return col.get(this.pos++);
        }

        @Override
        public boolean isDone()
        {
            return this.pos >= col.size();
        }

        @Override
        public String currentItem()
        {
            return col.get(this.pos);
        }
    }
}

Note

PS:例子中链表的迭代器那里也是用索引来做的,JDK的实现也是,迭代器实现关键就在于移动的cursor,适合用索引来表示

迭代器很强大(foreach),但是要注意在迭代器中修改数据结构的操作,虽然可以通过先备份的方式来隔离修改操作,但是可能会降低性能

posted on 2020-12-01 21:16  老鼠不上树  阅读(68)  评论(0)    收藏  举报