相信自己,请一定要相信自己
上一章简单介绍了访问者模式(十八), 如果没有看过, 请观看上一章
一. 迭代器模式
引用 菜鸟教程里面迭代器模式介绍: https://www.runoob.com/design-pattern/iterator-pattern.html
迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。
这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
迭代器模式属于行为型模式。
一.一 介绍
意图: 提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。
主要解决: 不同的方式来遍历整个整合对象。
何时使用: 遍历一个聚合对象。
如何解决: 把在元素之间游走的责任交给迭代器,而不是聚合对象。
关键代码: 定义接口:hasNext, next。
应用实例: JAVA 中的 iterator。
优点: 1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
缺点: 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
使用场景: 1、访问一个聚合对象的内容而无须暴露它的内部表示。 2、需要为聚合对象提供多种遍历方式。 3、为遍历不同的聚合结构提供一个统一的接口。
注意事项: 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
组成角色 | 具体 | 关系 |
---|---|---|
Iterator | MyIterator | 迭代器接口,是系统提供,含义 hasNext, next, remove |
ConcreteIterator | BookShelfIterator,BookShelfReverseIterator | 具体的迭代器类,管理迭代 |
Aggregate | Aggregate | 一个统一的聚合接口, 将客户端和具体聚合解耦 |
ConcreteAggreage | BookShelf | 具体的聚合持有对象集合, 并提供一个方法,返回一个迭代器, 该迭代器可以正确遍历 集合 |
二. 迭代器实例
二.一 迭代的实体对象 Book
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book implements Serializable {
private String name;
private String author;
}
二.二 迭代器接口 MyIterator
可以直接使用 java 提供的 java.util.Iterator 接口
public interface MyIterator<T> {
public boolean hasNext();
public T next() ;
}
二.三 聚合接口 Aggregate
定义了两个迭代器
public interface Aggregate<T> {
/**
定义不同的迭代器
*/
public MyIterator<T> getInterator();
public MyIterator<T> getReverseInterator();
}
二.四 迭代器实现 BookShelfIterator
二.四.一 正序迭代器
public class BookShelfIterator implements MyIterator<Book>{
private BookShelf bookShelf;
private int index = 0;
public BookShelfIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf;
}
@Override
public boolean hasNext() {
return bookShelf.getLength() > index;
}
@Override
public Book next() {
Book bookAt = bookShelf.getBookAt(index);
index++;
return bookAt;
}
}
二.四.二 倒序迭代器
public class BookShelfReverseIterator implements MyIterator<Book>{
private BookShelf bookShelf;
private int index = -1;
public BookShelfReverseIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf;
this.index = bookShelf.getLength()-1;
}
@Override
public boolean hasNext() {
return index >= 0;
}
@Override
public Book next() {
Book bookAt = bookShelf.getBookAt(index);
index--;
return bookAt;
}
}
二.五 具体聚合接口 BookShelf
public class BookShelf implements Aggregate<Book>{
private List<Book> bookList = new ArrayList<>();
@Override
public MyIterator<Book> getInterator() {
return new BookShelfIterator(this);
}
@Override
public MyIterator<Book> getReverseInterator() {
return new BookShelfReverseIterator(this);
}
public Integer getLength() {
return bookList.size();
}
public void appendBook(Book book) {
this.bookList.add(book);
}
public Book getBookAt(Integer position) {
return this.bookList.get(position);
}
}
二.六 客户端调用
@Test
public void oneTest() {
BookShelf bookShelf = new BookShelf();
bookShelf.appendBook(new Book("第一本书","第一本书"));
bookShelf.appendBook(new Book("第二本书","第二本书"));
bookShelf.appendBook(new Book("第三本书","第三本书"));
bookShelf.appendBook(new Book("第四本书","第四本书"));
bookShelf.appendBook(new Book("第五本书","第五本书"));
MyIterator<Book> interator = bookShelf.getInterator();
while (interator.hasNext()) {
Book book = interator.next();
log.info("打印信息: {}", book);
}
// 打印反转的信息.
log.info(">>>> 倒序的信息");
MyIterator<Book> reverseInterator = bookShelf.getReverseInterator();
while (reverseInterator.hasNext()) {
Book book = reverseInterator.next();
log.info("打印信息: {}", book);
}
}
在 Java 中 集合迭代的话,是很方便的
正序迭代:
@Test
public void twoTest() {
List<Book> bookList = new ArrayList<>();
bookList.add(new Book("第一本书","第一本书"));
bookList.add(new Book("第二本书","第二本书"));
bookList.add(new Book("第三本书","第三本书"));
bookList.add(new Book("第四本书","第四本书"));
bookList.add(new Book("第五本书","第五本书"));
Iterator<Book> iterator = bookList.iterator();
while (iterator.hasNext()) {
Book book = iterator.next();
log.info("打印信息: {}", book);
}
}
优点
-
提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。
-
隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成。
-
提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。
在聚合类中,我们把 迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。 而如果遍历方式改变的话,只影响到了迭代器。
4) 当要展示一组相似对象,或者遍历一组相同对象时使用, 适合使用迭代器模式
缺点
- 每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类
本章节的代码放置在 github 上:
https://github.com/yuejianli/DesignPattern/tree/develop/Iterator
谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!