zoukankan      html  css  js  c++  java
  • Iterator模式----一个一个遍历

    说起遍历,我立马就想到for循环,增强for循环,foreach循环这类的循环遍历,这个不错,既然有这么方便的遍历,为什么我们还要学习Iterator这样的遍历呢?

    一个重要的理由是:引入Iterator后可以将遍历和实现分离开来

    此话怎讲?什么意思呢?

    来说明这样的一个场景:

    刚开始写程序时,我们用的是Array,我们自定义的时候指定大小,然后用for循环进行遍历的如火如荼,突然有一天,要求变了,数组大小可变,并且要求使用ArrayList来定义这个集合,那么是不是所有的原来定义为Array的集合都需要改变,并改变其遍历方式啊?这样是不是很麻烦了!

    那么问题来了,有没有一种方法或者模式,将遍历和实现分开呢?上面的遍历和实现是耦合在一块的,通过for循环来实现遍历,将for循环绑定到遍历上,如果for循环没法实现了(比如上面,Array被ArrayList代替了,那么for循环的长度由length变为size()了),那么遍历就泡汤了。呵呵,当然有这种方法了,那就是Iterator方式了。

    怎么把这遍历和实现分离开呢?请看下文详细分解

    这里有四个角色,分别是Iterator,CustomeIterator,Aggregate,CustomeAggregate;四个角色,这四个角色对应的不同的用处,具体如下:

    Itertor:这个角色是个接口,用来定义顺序逐个遍历元素的API,包含hasNext和next两个方法。

    CustomeIterator:这个是实现Iterator的具体类,用来处理实际上的工作,包含了遍历集合必须的信息(需要遍历的集合以及集合对应的下标)

    Aggregate:定义创建Iterator的接口API,

    CustomeIterator:实现Aggregate接口并制定Iterator实现的具体类CustomeIterator,并将自己指定为CustimeIterator需要的集合

    其类图如下所示:

    下面是测试案例

    1,java util 的Iterator类,这个来自于java.util.Iterator,

    2,自定义的BookShelfIterator类

    package ModelItertor;
    
    import java.util.Iterator;
    
    public class BookShelfIterator implements Iterator {
        private int index;
        private BookShelf bookShelf;
        
        public BookShelfIterator(BookShelf bookShelf){
            this.bookShelf = bookShelf;
            this.index = 0;
        }
        
        public boolean hasNext() {
            return index<this.bookShelf.getLength();
        }
    
        public Object next() {
            Book book = this.bookShelf.getBookAt(index);
            index++;
            return book;
        }
    
    }
    View Code

    3,Aggregate类

    package ModelItertor;
    import java.util.Iterator;
    
    public interface Aggregate {
        public abstract Iterator iterator();
    }
    Aggregate

    4,自定义的BookShelf类

    package ModelItertor;
    
    import java.util.Iterator;
    
    public class BookShelf implements Aggregate {
    
        private Book[] books;
        private int last=0;
        public BookShelf(int maxsize){
            this.books = new Book[maxsize];
        }
        
        public Book getBookAt(int i){
            if(i>=books.length){
                return books[books.length-1];
            }
            else{
                return books[i];
            }
        }
        
        public void appendBook(Book book){
            books[last] = book;
            last++;
        }
        
        public int getLength(){
            return this.last;
        }
        
        public Iterator iterator() {
            return new BookShelfIterator(this);
        }
    
    }
    View Code

    5,测试的main类

    package ModelItertor;
    import java.util.Iterator;
    public class Main {
    
        public static void main(String[] args) {
            BookShelf bookShelf = new BookShelf(4);
            bookShelf.appendBook(new Book("A"));
            bookShelf.appendBook(new Book("B"));
            bookShelf.appendBook(new Book("C"));
            bookShelf.appendBook(new Book("D"));
            Iterator it = bookShelf.iterator();
            while(it.hasNext()){
                Book book = (Book)it.next();
                System.out.println(book.getName());
            }
        }
    
    }
    Main

    最终结果

    A
    B
    C
    D

    那么,还是最上面的问题,为什么搞这么复杂呢?

    现在有这样的一个需求,书的数量是可变的,也就是集合由以前的Array变为ArrayList,那么,我们只需要修改一下CustomeAggrator类的实现规则即可,对Iterator的类根本不用做任何改变,改变后的BookShelf类如下

    package ModelItertor;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class BookShelfList implements Aggregate {
    
        private List bookList;
        
        public BookShelfList(int size){
            this.bookList = new ArrayList(size);
        }
        
        public Book GetBookAt(int i){
            return (Book) bookList.get(i);
        }
        
        public Iterator iterator() {
            return new BookShelfListIterator(this);
        }
        
        public int getLength(){
            return bookList.size();
        }
        
        public void appendBook(Book book){
            bookList.add(book);
        }
    }
    View Code

    测试main方法如下

    package ModelItertor;
    import java.util.Iterator;
    public class Main {
    
        public static void main(String[] args) {    
            BookShelfList booklist = new BookShelfList(2);
            booklist.appendBook(new Book("E"));
            booklist.appendBook(new Book("F"));
            booklist.appendBook(new Book("G"));
            booklist.appendBook(new Book("H"));
            
            Iterator it2 = booklist.iterator();
            while(it2.hasNext()){
                Book book = (Book)it2.next();
                System.out.println(book.getName());
            }
        }
    
    }
    View Code
  • 相关阅读:
    关于js计算非等宽字体宽度的方法
    [NodeJs系列]聊一聊BOM
    Vue.js路由管理器 Vue Router
    vue 实践技巧合集
    微任务、宏任务与Event-Loop
    事件循环(EventLoop)的学习总结
    Cookie、Session和LocalStorage
    MySQL 树形结构 根据指定节点 获取其所在全路径节点序列
    MySQL 树形结构 根据指定节点 获取其所有父节点序列
    MySQL 创建函数报错 This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators
  • 原文地址:https://www.cnblogs.com/ningheshutong/p/6585438.html
Copyright © 2011-2022 走看看