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
  • 相关阅读:
    将指定json格式的内容,写入文件中,构造测试数据
    shell对比用=时 记得加空格
    scp带私钥使用以及免密配置
    kafka知识补充
    根据frm和ibd文件恢复数据库表结构和数据
    登录页面 逻辑:当用户进来的时候, 全局检查一下是否有用户的信息,如果用则显示用户信息页面;没有,则显示用户登录页面
    理解Spring 容器、BeanFactory 以及 ApplicationContext
    Java 中 CAS
    volatile 关键字
    JenKins docker 集群
  • 原文地址:https://www.cnblogs.com/ningheshutong/p/6585438.html
Copyright © 2011-2022 走看看