004-行为型-04-迭代器模式(Iterator)
一、概述
提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。
迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
迭代模式使用比较少,JDK集合也提供了Iterator的具体实现,可以直接拿来用,不必自己实现
1.1、适用场景
1、访问一个聚合对象的内容而无须暴露它的内部表示。
2、需要为聚合对象提供多种遍历方式。
3、为遍历不同的聚合结构提供一个统一的接口。
1.2、优缺点
优点: 1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
缺点:由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
1.3、类图角色及其职责

迭代模式的角色和职责
1、Iterator(迭代器接口):
该接口必须定义实现迭代功能的最小定义方法集
比如提供hasNext()和next()方法。
2、ConcreteIterator(迭代器实现类):
迭代器接口Iterator的实现类。可以根据具体情况加以实现。
3、Aggregate(容器接口):
定义基本功能以及提供类似Iterator iterator()的方法。
4、concreteAggregate(容器实现类):
容器接口的实现类。必须实现Iterator iterator()方法。
1.4、演进过程
1.4.1、初始化
创建一个容器中要存储的内容Book
public class Book {
private String id;
private String name;
private double price;
public Book(String id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public void display() {
System.out.println("ID=" + id + ",\tname=" + name + ",\tprice" + price);
}
}
创建一个容器BookList
public class BookList {
//容器内部还是一个List,也可以用数组
private List<Book> bookList = new ArrayList<Book>();
private int index;
//添加书籍
public void addBook(Book book){
bookList.add(book);
}
//删除书籍
public void removeBook(Book book){
int bookIndex = bookList.indexOf(book);
bookList.remove(bookIndex);
}
//判断是否有下一本书
public boolean hasNext(){
if(index >= bookList.size()){
return false;
}
return true;
}
//获得下一本书
public Book getNext(){
return bookList.get(index++);
}
//获取集合长度
public int getSize(){
return bookList.size();
}
//根据index获取Book
public Book getByIndex(int index){
return bookList.get(index);
}
}
接下来,就是迭代容器了
方式一、(由容器自己实现顺序遍历。直接在容器类里直接添加顺序遍历方法)
@Test
public void test1() {
BookList bookList = new BookList(); Book book1 = new Book("001","设计模式",200);
Book book2 = new Book("002","Java核心编程",200);
Book book3 = new Book("003","计算机组成原理",200); bookList.addBook(book1);
bookList.addBook(book2);
bookList.addBook(book3); while(bookList.hasNext()){
Book book = bookList.getNext();
book.display();
}
}
输出
ID=001, name=设计模式, price200.0
ID=002, name=Java核心编程, price200.0
ID=003, name=计算机组成原理, price200.0
方式二、让调用者自己实现遍历。直接暴露数据细节给外部)
@Test
public void test2() {
BookList bookList = new BookList(); Book book1 = new Book("001", "设计模式", 200);
Book book2 = new Book("002", "Java核心编程", 200);
Book book3 = new Book("003", "计算机组成原理", 200); bookList.addBook(book1);
bookList.addBook(book2);
bookList.addBook(book3); for (int i = 0; i < bookList.getSize(); i++) {
Book book = bookList.getByIndex(i);
book.display();
}
}
结果同上
不使用迭代模式的缺点
以上方法1与方法2都可以实现对遍历,但有这些问题
1,容器类承担了太多功能:一方面需要提供添加删除等本身应有的功能;一方面还需要提供遍历访问功能。
2,往往容器在实现遍历的过程中,需要保存遍历状态,当跟元素的添加删除等功能夹杂在一起,很容易引起混乱和程序运行错误等。
应用迭代模式的条件
Iterator模式就是为了有效地处理按顺序进行遍历访问的一种设计模式,简单地说,Iterator模式提供一种有效的方法,可以屏蔽聚集对象集合的容器类的实现细节,而能对容器内包含的对象元素按顺序进行有效的遍历访问。
所以,Iterator模式的应用场景可以归纳为满足以下几个条件:
1、访问容器中包含的内部对象
2、按顺序访问
1.4.2、进化
用代码实现一下迭代模式,只需修改BookList即可,BookListIterator
public class BookListIterator {
//容器内部还是一个List,也可以用数组
private List<Book> bookList = new ArrayList<Book>();
private int index;
//添加书籍
public void addBook(Book book){
bookList.add(book);
}
//删除书籍
public void removeBook(Book book){
int bookIndex = bookList.indexOf(book);
bookList.remove(bookIndex);
}
//获取集合长度
public int getSize(){
return bookList.size();
}
//根据index获取Book
public Book getByIndex(int index){
return bookList.get(index);
}
//得到Iterator实例
public Iterator Iterator() {
return new Itr();
}
//内部类,Iterator实例(因为要使用容器的内部信息,所以要写成内部类)
private class Itr implements Iterator{
//判断是否有下一本书,将刚才hasNext()中内容复制过来即可
public boolean hasNext() {
if(index >= bookList.size()){
return false;
}
return true;
}
//获得下一本书,将刚才getNext()中内容复制过来即可
public Object next() {
return bookList.get(index++);
}
public void remove() {
}
}
}
测试
@Test
public void test3() {
BookListIterator bookList = new BookListIterator(); Book book1 = new Book("001","设计模式",200);
Book book2 = new Book("002","Java核心编程",200);
Book book3 = new Book("003","计算机组成原理",200); bookList.addBook(book1);
bookList.addBook(book2);
bookList.addBook(book3); Iterator iterator = bookList.Iterator();
while(iterator.hasNext()){
Book book = (Book) iterator.next();
book.display();
}
}
输出同上
可以看到,这和使用JDK提供集合的Iterator方法就一模一样了。
二、扩展
2.1 JDK
java.util.Iterator
java.util.ArrayList中的Itr
2.2 Mybatis
org.apache.ibatis.cursor.defaults.DefaultCursor的cursorIterator
c
004-行为型-04-迭代器模式(Iterator)的更多相关文章
- 【设计模式】行为型04迭代器模式(Iterator Pattern)
学习地址:http://www.runoob.com/design-pattern/iterator-pattern.html 迭代器模式,简单来说就是通过迭代的方式对集合进行遍历,在集合的学习中也一 ...
- 设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型)
设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型) 1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的 ...
- 迭代器模式 Iterator 行为型 设计模式(二十)
迭代器模式(Iterator) 走遍天下,世界那么大,我想去看看 在计算机中,Iterator意为迭代器,迭代有重复的含义,在程序中,更有“遍历”的含义 如果给定一个数组,我们可以通过for循 ...
- 设计模式系列之迭代器模式(Iterator Pattern)——遍历聚合对象中的元素
模式概述 模式定义 模式结构图 模式伪代码 模式改进 模式应用 模式在JDK中的应用 模式在开源项目中的应用 模式总结 说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修 ...
- 设计模式(十):从电影院中认识"迭代器模式"(Iterator Pattern)
上篇博客我们从醋溜土豆丝与清炒苦瓜中认识了“模板方法模式”,那么在今天这篇博客中我们要从电影院中来认识"迭代器模式"(Iterator Pattern).“迭代器模式”顾名思义就是 ...
- 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern)
原文:乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) 作者:weba ...
- 迭代器模式-Iterator(Java实现)
迭代器模式-Iterator 用于访问一个集合中的各个元素, 而又不会暴露集合的内部的细节. 本文展示的例子就是, 在猫群组里, 用迭代器遍历每一只猫. 本文章的例子的继承关系图如下: 其中: Cat ...
- Java 设计模式系列(十五)迭代器模式(Iterator)
Java 设计模式系列(十五)迭代器模式(Iterator) 迭代器模式又叫游标(Cursor)模式,是对象的行为模式.迭代子模式可以顺序地访问一个聚集中的元素而不必暴露聚集的内部表象(interna ...
- 设计模式学习--迭代器模式(Iterator Pattern)和组合模式(Composite Pattern)
设计模式学习--迭代器模式(Iterator Pattern) 概述 ——————————————————————————————————————————————————— 迭代器模式提供一种方法顺序 ...
- 二十四种设计模式:迭代器模式(Iterator Pattern)
迭代器模式(Iterator Pattern) 介绍提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示. 示例有一个Message实体类,某聚合对象内的各个元素均为该实体对象,现 ...
随机推荐
- 零基础Python教程-详说list有序集合
list是一种有序的集合,可以随时添加和删除其中的元素. 比如,列出你周围同事的名字,就可以用一个list表示: >>> classmates = ['Michael', 'Bob' ...
- Python文件的读写操作
Python文件的使用 要点:Python能够以文本和二进制两种形式处理文件. 1.文件的打开模式,如表1: 注意:使用open()函数打开文件,文件使用结束后耀使用close()方法关闭,释放文件 ...
- wait,waitpid学习测试
用man wait学习wait waitpid的使用 wait()函数功能:wait()函数使父进程暂停执行,直到它的一个子进程结束为止,该函数的返回值是终止运行的子进程的PID. 参数status所 ...
- ES中的分析和分析器
在ES存储的文档,进行存储时,会对文档的内容进行分析和分词 分析的过程: 首先,将一块文本分成适合于倒排索引的独立的 词条 , 之后,将这些词条统一化为标准格式以提高它们的“可搜索性”,或者 reca ...
- mysql在group by分组后查询第二条/第三条乃至每组中任意一条数据
昨天老板让我查询项目中(众筹),没人刚发起感召后,前三笔钱的入账时间和金额,这把大哥整懵逼了,group by在某些方面是好使,但这次不能为我所用了,获取第一笔进账是简单,可以用group by 直接 ...
- 洛谷 P3375 【模板】KMP字符串匹配 题解
KMP模板,就不解释了 #include<iostream> #include<cstdio> #include<cstring> #include<algo ...
- C#在WebApi 中使用Redis 的方法
首先Startup public void ConfigureServices(IServiceCollection services) { services.AddControllers(); // ...
- YAML_04 用user模块添加用户,并修改密码
ansible]# vim user.yml --- - hosts: cache remote_user: root vars: username: lisi tasks: ...
- 自用ajxa 后台管理请求
/** * 保存或者修改商品信息 * @returns */ function saveOrUpdateBaseGoodInfo(){ var json={}; var goodName=$.trim ...
- 洛谷 P1231教辅的组成
题目描述 /* s->练习册(1~b)->书(b+1~a+b)->答案(a+b+1~a+b+c)->t 但是可能会有多本练习册指向同一本书,这本书又可能会指向多本答案 这样每本 ...