设计模式——迭代器(Iterator)模式
- 概述
迭代器模式简单的说(按我目前的理解)就是一个类提供一个对外迭代的接口,方面调用者迭代。这个迭代接口至少包括两个方法:hasNext()--用于判断是否还有下一个,next()--用于取出下一个对象(或值)。而外部使用这个类(取出这个类中的对象或值)时,不用关心这个类存储对象或数据的具体数据结构,即使这个类的存储数据结构临时发生改变,调用者不作任何代码修改仍然可以正常工作。从而实现代码的可重用性和低耦合性。下面以实例说明。
- 实例
假设有两个书架(BookShelf),一个书架用数组Array的形式存放书,另一个书架用ArrayList的形式存放书,两个书架可以存放多本书(Book)的名字,Main方法通过书架取出书名打印出来。
传统模式:很容易想到第一个书架通过一个方法返回存放书的数组,另一个书架返回存放书的ArrayList。就像下面这样:
//传统模式:
public Book[] getBooks(){
return books;
}
//传统模式
public ArrayList<Book> getBooks(){
return books;
}
这样的缺点是什么呢?缺点在于当我们同时获取到这两个书架时,迭代输出的方式就有所不同,因为一个是数组,一个是List,这个很容易想到吧,可能你觉得很简单,但是如果有十个,有几十个用不同的数据结构存储呢,迭代的方式又要改。并且,如果我开始用的数组存放书,后来我又不想用数组而改用List存放呢?那岂不是既要修改存放书的代码的同时又要修改迭代输出的代码?Oh,No..太麻烦了吧。可能你会想自己写的代码,干嘛每个书架存放书的数据结构要不同呢?那如果不是自己写的呢?比如我现在要合并多个餐馆的菜单为一个菜单并输出打印,而这些菜单的存储方式肯定不同,很有可能这几个餐馆的代码都不是同一个人写的。这时候我们再去一个一个循环未免也太麻烦。
使用迭代器模式:既然我不同的书架存放书的数据结构不同,那我可以每个书架对外提供一个迭代接口,而每个接口都包含有hasNext方法和Next方法。这时在外部循环迭代输出时,就不用担心每个书架的书是怎样存放的,我只需要能通过Next方法取出书就可以了,就像下面这样:
数组存放:
public class BookShelf { private Book[] books;
private int last = 0; public BookShelf(int maxsize) {
this.books = new Book[maxsize];
} public Book getBookAt(int index){
return books[index];
} public void appendBook(Book book){
this.books[last] = book;
last++;
} public int getLength(){
return last;
} // //传统模式:
// public Book[] getBooks(){
// return books;
// } public Iterator iterator() {
// return new BookShelfIterator(this);
return new BookShelfIterator();
} class BookShelfIterator implements Iterator{
// private BookShelf bookShelf; //采用内部类,可以直接调用外部类方法,不用添加引用。
private int index ;
public BookShelfIterator() {
// this.bookShelf=bookShelf;
this.index = 0;
} @Override
public boolean hasNext() {
if (index < getLength()){
return true;
}else {
return false;
}
}
@Override
public Object next() {
Book book = getBookAt(index);
index++;
return book;
}
}
}
ArrayList存放:
import java.util.ArrayList; public class BookShelf1 { private ArrayList<Book> books ;//使用ArrayList实现 public BookShelf1(int maxsize) {
this.books = new ArrayList<>(maxsize);//初始大小
} public Book getBookAt(int index){
return books.get(index);
} public void appendBook(Book book){
this.books.add(book);
} public int getLength(){
return books.size();
} public Iterator iterator() {
return new BookShelfIterator();
} // //普通模式
//// public ArrayList<Book> getBooks(){
//// return books;
//// } class BookShelfIterator implements Iterator{
// private BookShelf bookShelf; //采用内部类,可以直接调用外部类方法,不用添加引用。
private int index ;
public BookShelfIterator() {
// this.bookShelf=bookShelf;
this.index = 0;
} @Override
public boolean hasNext() {
if (index < getLength()){
return true;
}else {
return false;
}
}
@Override
public Object next() {
Book book = getBookAt(index);
index++;
return book;
}
} }
而我们获取这两个书架的书时,只需要调用两个书架的iterator()方法就可以获取到同样的Iterator对象,这个对象中都包含两个相同的方法hasNext()和Next(),这样我们就很方便的迭代输出了,并且我们不用关心每个书架里面是通过数组还是list存放书的。就像下面这样:
ArrayList<Iterator> iterList = new ArrayList<>(); //存放Iterator
BookShelf bookShelf = new BookShelf(4);//实例化第一个书架
bookShelf.appendBook(new Book("Around the World in 80 Days"));
bookShelf.appendBook(new Book("Bible"));
bookShelf.appendBook(new Book("Daddy-Long-Legs"));
bookShelf.appendBook(new Book("Cinderella"));
Iterator it = bookShelf.iterator();
iterList.add(it); BookShelf1 bookShelf1 = new BookShelf1(4);//实例化第二个书架
bookShelf1.appendBook(new Book("Around the World in 80 Days__"));
bookShelf1.appendBook(new Book("Bible__"));
bookShelf1.appendBook(new Book("Daddy-Long-Legs__"));
bookShelf1.appendBook(new Book("Cinderella__"));
Iterator it1 = bookShelf1.iterator();
iterList.add(it1);
for (int i = 0; i < iterList.size(); i++) {
Iterator iterator = iterList.get(i);
while (iterator.hasNext()){
Book book = (Book) iterator.next();
System.out.println(book.getName());
}
}
- 完整代码
请移步:https://github.com/yyc007/DesignPatterns/
- 小结
使用迭代器模式,可以帮助我们编写可以复用的类,当这个类发生改变时,不需要对其它的类进行修改或者很小的修改即可应对。就上面的书架例子来说,不管BookShelf如何变化,只要BookShelf返回的Iterator类的实例没有问题(hasNext方法和Next方法都可以正常工作),即使调用方不对迭代输出的While循环做任何修改都可以正常工作。
设计模式——迭代器(Iterator)模式的更多相关文章
- 设计模式—迭代器Iterator模式
什么是迭代器模式? 让用户通过特定的接口访问容器的数据,不需要了解容器内部的数据结构. 首先我们先模仿集合中ArrayList和LinkedList的实现.一个是基于数组的实现.一个是基于链表的实现, ...
- Java 实现迭代器(Iterator)模式
类图 /** * 自己定义集合接口, 相似java.util.Collection * 用于数据存储 * @author stone * */ public interface ICollection ...
- 1、迭代器 Iterator模式 一个一个遍历 行为型设计模式
1.Iterator模式 迭代器(iterator)有时又称游标(cursor)是程序设计的软件设计模式,可在容器(container,例如链表或者阵列)上遍访的接口,设计人员无需关心容器的内容. I ...
- 设计模式C++描述----20.迭代器(Iterator)模式
一. 举例说明 我们知道,在 STL 里提供 Iterator 来遍历 Vector 或者 List 数据结构. Iterator 模式也正是用来解决对一个聚合对象的遍历问题,将对聚合的遍历封装到一个 ...
- 设计模式之Iterator模式
STL里的iterator就是应用了iterator模式. 一.什么是迭代模式 Iterator模式也叫迭代模式,是行为模式之一,它把对容器中包含的内部对象的访问委让给外部类,使用Iterator按顺 ...
- Java设计模式之Iterator模式
分类: [java]2013-07-15 10:58 917人阅读 评论(0) 收藏 举报 所谓Iterator模式,即是Iterator为不同的容器提供一个统一的访问方式.本文以java中的容器为例 ...
- Head First 设计模式 —— 10. 迭代器 (Iterator) 模式
思考题 public void printMenu() { PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu(); ArrayList ...
- 设计模式:Iterator模式
目的:将数据的存储和数据的查询分开,降低数据的耦合性 继承关系图: 例子: //定义迭代器接口 template<typename T> class Iterator { public: ...
- 设计模式之Iterator模式(2)
这篇文章比较简单,作一个笔记. 模拟Iterator. Iterator接口: package cn.asto.Interator; public interface Iterator { publi ...
随机推荐
- D. Mike and Feet---cf548D(最值)
题目链接:http://codeforces.com/problemset/problem/548/D 给你n个数,对于(1,n)长度,让你找到线段的最小值的最大值是多少 #include<io ...
- windows中的进程和线程
今天咱们就聊聊windows中的进程和线程 2016-09-30 在讨论windows下的进程和线程时,我们先回顾下通用操作系统的进程和线程.之所以称之为通用是因为一贯的本科或者其他教材都是这么说的: ...
- Flask用Flask-SQLAlchemy连接MySQL
安装 pip3 install Flask-SQLAlchemy 测试环境目录结构 settings.py DIALECT = 'mysql' DRIVER = 'pymysql' USERNAME ...
- VMware 虚拟机 Ubuntu 不能全屏问题
在刚安装完ubuntu后,屏幕不能全屏显示,此时: 1.安装VMware Tools 步骤: 1.1 进入ubuntu系统后,点击虚拟机上的[虚拟机]->[安装 vmware tools ...
- (2.5)Mysql之SQL基础——数据类型
(2.5)Mysql之SQL基础——数据类型 关键词:mysql数据类型 目录: 一.整数型 二.小数型(以下均不能使用无符号) 三.日期时间型 四.字符串型 一.整数型 额外参数示例: int [( ...
- 如何制作一款HTML5 RPG游戏引擎——第一篇,地图类的实现
一,话说天下大事 前不久看到lufy的博客上,有一位朋友想要一个RPG游戏引擎,出于兴趣准备动手做一做.由于我研究lufylegend有一段时间了,对它有一定的依赖性,因此就准备将这个引擎基于lufy ...
- String,StringBuffer和StringBuilder的区别
面试的时候经常问到的一个题:这里先说明下三者在JVM中的执行速度:StringBuilder > StringBuffer > String,原因且看下面慢慢阐述. 首先看一个概念,为啥一 ...
- 压力测试sysbench
sysbench是一个模块化的.跨平台.多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况.目前sysbench代码托管在launchpad上,项目地址:https://launc ...
- JAVA中的反射机制 (转)
反射,当时经常听他们说,自己也看过一些资料,也可能在设计模式中使用过,但是感觉对它没有一个较深入的了解,这次重新学习了一下,感觉还行吧! 一,先看一下反射的概念: 主要是指程序可以访问,检测和修改它本 ...
- HDU - 5909 Tree Cutting (树形dp+FWT优化)
题意:树上每个节点有权值,定义一棵树的权值为所有节点权值异或的值.求一棵树中,连通子树值为[0,m)的个数. 分析: 设\(dp[i][j]\)为根为i,值为j的子树的个数. 则\(dp[i][j\o ...