美文网首页设计模式
设计模式——迭代器模式

设计模式——迭代器模式

作者: 程序员will | 来源:发表于2019-11-05 11:04 被阅读0次

    什么是迭代器模式

    用迭代器来封装集合对象的遍历细节,使调用者能够通过统一的接口来实现对集合的遍历。

    迭代器也给集合对象提供了一定的保护,想要遍历集合,直接调用迭代器的方法就好了,我们不知道也不必知道集合内部的数据管理方式。

    举个例子

    有这样的一个需求。一家集团公司在北京和上海分别有一家子公司,每家公司内部有自己的部门,且自己提供了打印部门的方法。其中一个子公司以数组来保存部门列表,另外一个以ArrayList来保存。现在需要打印所有的部门。

    原始实现

    部门对象:

    //部门对象
    public class Dept {
        private String name;
    
        public Dept(String name){
            this.name= name;
        }
    
        public String getName(){
            return this.name;
        }
    }
    
    //北京分公司
    public class BJBranch {
        ArrayList<Dept> depts;
    
        public BJBranch(){
            depts = new ArrayList<Dept>();
            //添加部门
            depts.add(new Dept("北京-财务部"));
            depts.add(new Dept("北京-研发部"));
            depts.add(new Dept("北京-开发部"));
        }
    
        public ArrayList<Dept> getDepts(){
            return depts;
        }
    }
    
    //上海分公司
    public class SHBranch {
        Dept[] depts;
    
        public SHBranch(){
            depts = new Dept[3];
            //添加部门
            depts[0] = new Dept("上海-财务部");
            depts[1] = new Dept("上海-研发部");
            depts[2] = new Dept("上海-开发部");
        }
    
        public Dept[] getDepts(){
            return depts;
        }
    }
    

    测试代码

    public class TestOld {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            BJBranch BJ             = new BJBranch();
            ArrayList<Dept> BJDepts = BJ.getDepts();
            SHBranch SH     = new SHBranch();
            Dept[] SHDepts  = SH.getDepts();
            //遍历两家子公司的所有部门
            /** 由于类型不同,需要两次循环 **/
            for(int i=0;i<BJDepts.size();i++){
                System.out.println(BJDepts.get(i).getName());
            }
            for(int i=0;i<SHDepts.length;i++){
                System.out.println(SHDepts[0].getName());
            }
        }
    }
    

    从上面的代码中可以看出,由于两家子公司的实现方式不一样,造成循环遍历时自能使用对应的方式来遍历,造成相当大的不便。

    改造,使用迭代器模式

    //迭代器接口
    public interface Iterator {
        boolean hasNext();
        Object next();
    }
    
    //北京分公司的部门迭代器
    public class BJBranchIterator implements Iterator{
        ArrayList<Dept> depts;
        int position    = 0;
        public BJBranchIterator(ArrayList<Dept> depts){
            this.depts = depts;
        }
        @Override
        public boolean hasNext() {
            if(position>=depts.size() || depts.get(position)==null){
                return false;
            }else{
                return true;
            }
        }
    
        @Override
        public Object next() {
            Dept dept = depts.get(position);
            position  = position + 1;
            return dept;
        }
    
    }
    
    //改造后的北京分公司
    public class BJBranch {
        ArrayList<Dept> depts;
    
        public BJBranch(){
            depts = new ArrayList<Dept>();
            //添加部门
            depts.add(new Dept("北京-财务部"));
            depts.add(new Dept("北京-研发部"));
            depts.add(new Dept("北京-开发部"));
        }
    
        /*public ArrayList<Dept> getDepts(){
            return depts;
        }*/
    
        //改造为返回Iterator对象,而不是ArrayList
        public Iterator createrIterator(){
            return new BJBranchIterator(depts);
        }
    }
    
    //上海分公司的部门迭代器
    public class SHBranchIterator implements Iterator{
        Dept[] depts;
        int position    = 0;
        public SHBranchIterator(Dept[] depts){
            this.depts = depts;
        }
        @Override
        public boolean hasNext() {
            if(position>=depts.length|| depts[position]==null){
                return false;
            }else{
                return true;
            }
        }
    
        @Override
        public Object next() {
            Dept dept = depts[position];
            position  = position + 1;
            return dept;
        }
    
    }
    
    //改造后的上海分公司
    public class SHBranch {
        Dept[] depts;
    
        public SHBranch(){
            depts = new Dept[3];
            //添加部门
            depts[0] = new Dept("上海-财务部");
            depts[1] = new Dept("上海-研发部");
            depts[2] = new Dept("上海-开发部");
        }
    
        /*public Dept[] getDepts(){
            return depts;
        }*/
    
        //改造为返回Iterator对象,而不是数组
        public Iterator createrIterator(){
            return new SHBranchIterator(depts);
        }
    }
    
    //使用迭代器模式后的代码实现
    public class TestNew {
    
        public static void main(String[] args) {
            Iterator BJ = new BJBranch().createrIterator();
            Iterator SH = new SHBranch().createrIterator();
    
            printDeptName(BJ);
            printDeptName(SH);
        }
    
        private static void printDeptName(Iterator iterator){
            while(iterator.hasNext()){
                Dept dept = (Dept) iterator.next();
                System.out.println(dept.getName());
            }
        }
    }
    

    从改造后的代码中可以看出,使用迭代器模式改造后,成功的屏蔽了北京与上海分公司遍历的差异。

    至此,我们就手写了一个简单的迭代器模式。

    总结

    由于迭代器的方便性与必要性,Java1.5之后就提供了对Iterator的支持,目前很多集合对象都支持Iterator,例如Set, List, Map, SortedSet, SortedMap, HashSet, TreeSet, ArrayList, LinkedList, Vector等等。

    唯一不支持迭代器的可能就是数组吧(栈,队列这些特殊的除外)。

    Java.util.Iterator接口定义了三个方法(除hasNextnext方法外还有remove方法);

    迭代器的隐式调用

    很多语言都支持for each(或者 for in)循环,其内部实现就是调用了迭代器完成遍历。当然,只是一个小常识,更重要的是学会迭代器的设计原理,在需要的时候定义自己的迭代器。

    扩展

    迭代器模式本身比较简单,甚至我们已经不需要去定义自己的迭代器了(API提供提供的迭代器接口几乎可以满足我们的需要了)。

    但迭代器与组合模式结合起来,可以做一些不可思议的事情。

    相关文章

      网友评论

        本文标题:设计模式——迭代器模式

        本文链接:https://www.haomeiwen.com/subject/fjjsbctx.html