设计模式之适应设计模式_Iterator模式_一个一个遍历
1、示例程序
1.1、场景
讲书放Book到书架上
BookShelf
,然后使用iterator遍历讲书的名字信息打印出来
1.2、UML图
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接口负责定义了两个方法,next
和hashNext
方法
1、next
用于获取集合中某个索引的下一个元素
2、hasNext
用于判断是否存在下一个元素
2.3、ConcreteAggregate(具体的集合,类似于ArrayList)
该角色会实现Aggregate
角色所以定义的接口,它会创建出具体的Iterator角色,即 ConcreteIterator
角色 ,示例程序中 BookShelf
扮演这个角色
2.4、Concretelterator
( 具体的迭代器)
该角色负责实现iterator
所定义的接口,也就是我们上面的BookShelfIterator
,**示例程序中,该角色包含了遍历集合所必须的信息 ,也就是说包含集合 BookShelf**
1、BookShelf 书架
2、遍历的下标index
2.5、迭代模式的类图
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指向下一个元素