关于设计模式:浅谈设计模式-迭代器模式十一

56次阅读

共计 4210 个字符,预计需要花费 11 分钟才能阅读完成。

浅谈设计模式 – 迭代器模式(十一)

前言

​ 迭代器模式通常只须要晓得该模式的实现原理和理解结构图即可,在设计模式当中本人实现的状况简直是没有的,所以这个模式简略的过一遍。

什么是迭代器模式

定义:提供程序的办法拜访一个聚合对象的各个元素,同时又不会裸露外部的性能

迭代器模式通过接管遍历的细节,让提供方不用关怀迭代的具体细节,只须要提供对应的聚合对象即可。

迭代器模式和加强的 FOR 循环:

Jdk1.5 之后,将泛型和加强 for 循环退出到语言体系,能够间接对于汇合的内容进行 for 循环查看,其实实质上还是调用了 iterator 办法,而 java 通过语法糖的模式为咱们进行的遍历的暗藏。

迭代器模式结构图

​ 迭代器模式的结构图如下:

Aggregate:聚合对象的独特接口,定义了具备遍历性能的聚合对象,通过定义创立迭代器的接口来建设与迭代器的组合
ConcreateAggregate:具体的迭代器实现对象,通过接口办法返回具体的迭代器实现
Iterator:迭代器接口,定义迭代器的对立标准,所以派生类都须要强制依照接口标准执行迭代器的实现。保障迭代器具备类似的行为。ConcreteIterator:具体的迭代器实现,外部聚合对象的同时,能够扩大迭代器的遍历形式,比方 ListIterator。

迭代器模式特点

  • 迭代器将遍历的细节进行了封装,聚合对象不须要在关怀客户端如何操作外部的变量,而是通过委托给迭代器的模式交由迭代器去实现具体的遍历细节。
  • 迭代器能够在 不裸露内部结构的同时让外界能够拜访到外部的聚合对象,所以即便是齐全不同的对象也能够对立看待和解决。
  • 迭代器是一种职责的转移,将遍历的工作从本来的聚合对象中进行独立,能在 不改变数据结构的同时扭转数据的操作形式

迭代器的注意事项:

  1. 须要留神迭代器存在 外部的迭代器 内部的迭代器,外部的迭代器供对象自身应用不对外开放,内部的迭代器通过办法返回给调用方应用。
  2. 每个责任对应一个区域,超过区域象征多了一个责任,遍历和数据操作实际上是两个操作,应该辨别看待。
  3. 留神迭代器是如何体现繁多职责的准则,他剥离了遍历对象的性能,将其封装到一个迭代器外部进行应用。
  4. 好的迭代器该当具备“疾速失败机制”,目标是为了避免操作外部元素的指针越界,同时及时告诉客户端遍历异样。
  5. 如果想让办法不反对某些性能,最好应用异样机制揭示客户端我不反对某些操作。

案例

​ 光有实践还是不够的,这里配合代码解说迭代器是如何实现解耦聚合对象的遍历的。

模仿场景:

​ 因为迭代器在理论工作中应用概率 简直为 0 ,这里设置的场景比较简单

​ 咱们应用 window 最常见的文件系统来作为案例,咱们通常进入不同的磁盘,首先就是对该磁盘上面的第一级目录进行遍历,同时咱们依据遍历形式的不同,能够将页面展现为分组,依照工夫排序,显示不同的详略信息 ….. 这些性能的实质都是遍历,只不过遍历的模式不同,为了实现对于菜单的不同模式遍历,咱们通过定义不同迭代器来实现这一个指标。

​ 接着,咱们会发现迭代的品种丰盛还不够,咱们还须要迭代其余的内容,比方工作管理器须要迭代不同的过程,同样也蕴含了排序的或者暗藏局部过程等等一系列的性能,所以须要让不同的对象能够撑持类似的迭代操作,并且能够自在的替换迭代的形式,当然这部分性能不会放入案例局部,案例局部为简略的迭代器实现。

具体实现

​ 在进行具体的编码之前,先检查一下须要的根本构建类:

Travelsable:定义对象具备迭代的性能接口。MissionBoard:任务栏,储存根本的工作信息,提供迭代器供内部展现。TaskItemlIterator:工作迭代器,用于工作的迭代操作
ConcreteCatalogIterator:目录迭代器的实现具体子类,定义了不同的迭代品种。TaskItem 工作项,定义一个工作的内容
Computer 电脑,只须要治理任务栏和文件管理器即可。FileManager 文件管理器,负责管理文件夹的内容
FileIterator 文件迭代器,治理文件夹的迭代操作
FileItem 文件项

​ 上面间接依照结构图构建具体代码:

// 电脑,只须要治理任务栏和文件管理器即可。public class Computer {

    private FileManager fileManager;
    private MissionBoard missionBoard;

    public Computer(FileManager fileManager, MissionBoard missionBoard) {
        this.fileManager = fileManager;
        this.missionBoard = missionBoard;
    }

    public void display(){Iterator fileManagerIterator = fileManager.createIterator();
        Iterator missionBoardIterator = missionBoard.createIterator();

        while (fileManagerIterator.hasNext()){Object next = fileManagerIterator.next();
            System.out.println(next);
        }

        while (missionBoardIterator.hasNext()){Object next = missionBoardIterator.next();
            System.out.println(next);
        }

    }
}

// 文件项
public class FileItem {

    private String fileName;

    private String editDate;

    private String ceateDate;

    private long size;

       // 省略局部内容
}

// 工作项
public class TaskItem {

    private String name;

    private int size;

    // 省略局部内容
}

// 迭代器标准接口
public interface Travelsable<E extends Object>{

    /**
     * 创立迭代器的办法
     * @return
     */
    Iterator<E> createIterator();}

// 任务栏,治理工作项. 实现接口,反对迭代操作
public class MissionBoard implements Travelsable {

    private Stack<TaskItem> taskItems;

    public MissionBoard() {taskItems = new Stack<>();
        taskItems.push(new TaskItem("工作 1", 10));
        taskItems.push(new TaskItem("工作 2", 1230));
        taskItems.push(new TaskItem("工作 3", 123));
        taskItems.push(new TaskItem("工作 4", 414));
        taskItems.push(new TaskItem("工作 5", 555));
    }

    @Override
    public Iterator createIterator() {return new TaskItemlIterator(taskItems);
    }

}

// 文件管理器,管理文件项,实现接口并且反对迭代操作
public class FileManager implements Travelsable{private FileItem[] fileItems;

    public FileManager() {this.fileItems = new FileItem[10];
        Random random = new Random(10000);
        for (int i = 0; i < fileItems.length; i++) {fileItems[i] = new FileItem("文件"+i, random.nextInt(2000));
        }
    }

    @Override
    public Iterator createIterator() {return new FileIterator(fileItems);
    }

}

// 文件迭代器
public class FileIterator implements Iterator{private FileItem[] fileItems;

    private int index;

    public FileIterator(FileItem[] fileItems) {
        this.fileItems = fileItems;
        this.index = 0;
    }

    @Override
    public boolean hasNext() {return index++ < fileItems.length - 1;}

    @Override
    public Object next() {return fileItems[index];
    }

    @Override
    public void remove(Object ele) {throw new UnsupportedOperationException("数组不反对以后操作");
    }
}

// 工作迭代器
public class TaskItemlIterator implements Iterator{

    private Stack<TaskItem> taskItems;

    public TaskItemlIterator(Stack<TaskItem> taskItems) {this.taskItems = taskItems;}

    @Override
    public boolean hasNext() {if(taskItems.isEmpty()){return false;}
        TaskItem peek = taskItems.peek();
        return peek != null;
    }

    @Override
    public Object next() {return taskItems.pop();
    }

    @Override
    public void remove(Object ele) {taskItems.remove(ele);
    }
}

以上就是迭代的大抵实现案例代码,古代编程根本不会本人去设计迭代器,所以理解概念和晓得样板代码即可。

总结:

​ 迭代器在 JAVA 语言中根本曾经实现到汇合当中,当咱们遍历汇合的时候,其实就是在应用迭代器,迭代器通过 封装遍历 解耦了一堆对象的遍历和创立工作,将迭代的细节封装到一个黑盒当中,内部只须要调用接口就能够操作汇合的数据。

正文完
 0