设计模式之适应设计模式_Iterator模式_一个一个遍历

前言

博主github

博主个人博客http://blog.healerjean.com

标题上已经写明了,就是一个一个遍历

1、示例程序

1.1、场景

讲书放Book到书架上BookShelf,然后使用iterator遍历讲书的名字信息打印出来

1.2、UML图

[外链图片转存失败(img-ecg2u7lL-1566550398888)(https://raw.githubusercontent.com/HealerJean/HealerJean.github.io/master/blogImages/1558680180085.png)]

1.3、程序代码设计

1.3.1、Aggregate 接口: 集合接口(类似于List) 英文名 :合计、集合体

/**
 * Aggregate 英文名 合计、集合体 类似于List
 */
public interface Aggregate {

     /**
      * 迭代器接口
      */
     Iterator iterator();


}


1.3.2、Iterator 接口 :迭代器

/**
 * 遍历集合的迭代器
 */
public interface Iterator {
    boolean hasNext();
    Object next();
}

1.3.3、Book 类: 书


/**
 * 表示书的类
 */
@Data
@AllArgsConstructor
public class Book {

    private String name;

}

1.3.4、:BookShelf:类:书架(实现了集合接口Aggregate 相当于ArrayList)
/**
 * 1、表示书架的类 存放书架的长度和书架的集合;
 * 2、实现集合接口 Aggregate 并实现方法iterator
 *
 * List<Book> books; 书架上放书
 * size 已经放了几本书 初始为 0,
 *
 * 问,为什么不用books的size来判断的放了多少本书,而是用last,
 * 我们这个设计模式叫Iterator 一个个读取,上面的list集合我们只用来存放数据,而不作为其他用户
 */
public class BookShelf implements Aggregate {

    private List<Book> books;

    /**已经放了几本书,从0开始 */
    private int size = 0;

    public BookShelf(){
        books = new ArrayList<>() ;
    }


    /**
     * 放书,每次放入
     * @param book
     */
    public void addBook(Book book) {
        this.books.add(book);
        size++;
    }

    /**
     * 根据位置取书
     */
    public Book getBookAt(int index) {
        return books.get(index);
    }


    /**
     * 获取目前书架长度
     * @return
     */
    public int getLength() {
        return size;
    }

    /**
     * 获取一个数据的读取工具 迭代器
     */
    @Override
    public Iterator iterator() {
        return new BookShelfIterator(this);
    }
}

1.3.5、BookShelfIterator 类: 迭代器Iterator 实现类
package com.hlj.moudle.design.D01_适应设计模式.D01_Iterator模式.Sample;


/**
 * 遍历书架的迭代器 类
 * 迭代器需要的参数
 * 1、要迭代的对象 bookShelf书架
 * 2、迭代到哪里了index
 */
public class BookShelfIterator implements Iterator {

    /** 要迭代的对象 bookShelf书架  */
    private BookShelf bookShelf;

    /** 迭代到哪里了index */
    private int index;

    /**
     * 初始化迭代器,从 0 开始准备迭代
     * @param bookShelf
     */
    public BookShelfIterator(BookShelf bookShelf) {
        this.bookShelf = bookShelf;
        this.index = 0;
    }

    /**
     * 判断书架是否还有书
     * @return
     */
    @Override
    public boolean hasNext() {
        if (index < bookShelf.getLength()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 依次遍历 书架上的书
     * @return
     */
    @Override
    public Object next() {
        Book book = bookShelf.getBookAt(index);
        index++;
        return book;
    }
}

1.3.6、测试Main
package com.hlj.moudle.design.D02_适应者设计模式.D01_Iterator模式.Sample;



public class Main {
    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf();
        bookShelf.appendBook(new Book("Around the World in 80 Days"));
        bookShelf.appendBook(new Book("Bible"));
        bookShelf.appendBook(new Book("Cinderella"));
        bookShelf.appendBook(new Book("Daddy-Long-Legs"));
        Iterator it = bookShelf.iterator();
        while (it.hasNext()) {
            Book book = (Book)it.next();
            System.out.println(book.getName());
        }
    }
}


Around the World in 80 Days
Bible
Cinderella
Daddy-Long-Legs

2、Iterator模式中的各种角色

2.1、Aggregate (接口 集合 类似于List)

该角色负责创建Iterator接口

2.2、Iterator(接口 迭代器 )

iterator接口负责定义了两个方法,nexthashNext方法

1、next 用于获取集合中某个索引的下一个元素

2、hasNext用于判断是否存在下一个元素

2.3、ConcreteAggregate(具体的集合,类似于ArrayList)

该角色会实现Aggregate 角色所以定义的接口,它会创建出具体的Iterator角色,即 ConcreteIterator角色 ,示例程序中 BookShelf扮演这个角色

2.4、Concretelterator( 具体的迭代器)

该角色负责实现iterator所定义的接口,也就是我们上面的BookShelfIterator ,**示例程序中,该角色包含了遍历集合所必须的信息 ,也就是说包含集合 BookShelf**

1、BookShelf 书架

2、遍历的下标index

2.5、迭代模式的类图

[外链图片转存失败(img-d9OEOazh-1566550398889)(https://raw.githubusercontent.com/HealerJean/HealerJean.github.io/master/blogImages/1558683119564.png)]

3、扩展思路

Book数组我们直接for循环打印出来不久好了,为啥还要使用Iterator这个东西呢 ,

原因:引入Iterator后可以讲遍历与实现分离开来 ,不管实现如何变化,都可以使用Iterator,这里只使用了Iterator的hasNext方法和next方法,并没有调用BookShelf方法,也就是说While循环不依赖BookShelf的实现

举例:如果编写BookShel 书架的开发人员觉得不使用List集合来管理书本,而是使用其他的,比如使用数据来管理书本,,这样的话,不管书架 BookShel如何变化,只要BootShelf的iterator的方法能够正确返回Iterator的实例 即使不对while做任何修改,代码都可以正常工作。

Iterator it = bookShelf.iterator();
while (it.hasNext()) {
    Book book = (Book)it.next();
    System.out.println(book.getName());
}

4、容易出错的地方

4.1、容易容错下一个,很容易在next方法上出错, next方法是,返回当前的元素,index指向下一个元素



感兴趣的,欢迎添加博主微信

哈,博主很乐意和各路好友交流,如果满意,请打赏博主任意金额,感兴趣的在微信转账的时候,备注您的微信或者其他联系方式。添加博主微信哦。

请下方留言吧。可与博主自由讨论哦

微信 微信公众号 支付宝
微信 微信公众号 支付宝
posted @ 2019-08-23 16:54  HealerJean  阅读(167)  评论(0编辑  收藏  举报