在实现生活以及程序设计中,经常要访问一个聚合对象中的各个元素,如"数据结构"中的链表遍历,通常的做法是将链表的创建和遍历都放在同一个类中,但这种方法不利于程序的扩展, 如果要更换遍历方法就必须修改程序源码,这违背了开闭原则"",既然遍历方法封装到聚合类中不可取,那聚合类不提供遍历方法,遍历方法由用户自行实现可行吗?答案是同样不可取,因为这种方式会存在两个缺点:
1.暴露了聚合类的内部表示,使其数据不安全;
2.增加了客户端的负担;
迭代器模式能较好的克服以上缺点,它在 客户访问类 与 聚合类之间 插入一个迭代器,这分离了聚合对象与其其遍历行为,对客户也隐藏了内部细节,且满足"单一职责原则" 和 "开闭原则" 如 Java 中的 Collection、List、Set、Map等都包含了迭代器;
迭代器模式在生活中应用的比较广泛,如:物流系统中的传送带,不管传送的是什么物品,都会被打包成一个个箱子.且有一个统一的二维码,这样我们不需要关心箱子里是什么,在分发时只需一个个检查发送的目的地即可.再比如,我们平时乘坐交通工具,都是统一刷卡进站,却不需乘车人信息;
迭代器模式(Iterator pattern)的定义:提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示;
1) 迭代器模式,是常用的设计模式,属于行为模式
2) 如果我们的集合元素是用不同的方式实现的,有数组,还有java集合类当客户端要遍历这些集合元素时,就要使用多种遍历的方式,
且还会暴露元素的内部结构,这时可考虑使用迭代器模式解决;
3) 迭代器模式,提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需知道集合对象的底层表示(不暴露其内部结构);
1) 提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了;
2) 隐藏了聚合的内部结构,客户端要遍历聚合的时候,只能取得迭代器,而不会知道聚合的具体组成;
3) 提供了一种设计思想,即一个类应该只有一个引发变化的原因(单一职责原则),在聚合类中我们把迭代器分开,就是把管理对象集合
和 遍历对象集合 的责任分开,这样集合改变的话,只影响到聚合对象,而如果遍历方式改变只影响迭代器;
每个聚合对象都要一个迭代器, 会生成多个迭代器不好管理类,一定程度上增加了系统的复杂性;
当展示一组相似对象,或 遍历一组相同对象时使用迭代器模式;
1)Aggregate(抽象聚合): 定义存储、添加、删除聚合对象以及创建迭代器对象的接口;
2)ConcreteAggregate(具体聚合): 会持有对象集合,并提供一个方法,返回一个具体迭代器实例,该迭代器可以正确遍历聚合;
3)Iterator(抽象迭代器): 定义访问和遍历聚合元素的接口(系统提供),含有 hasNext. next, remove 等方法;
4)ConcreteIterator(具体的迭代器): 实现抽象迭代器接口方法,完成对聚合对象的遍历,记录遍历的当前位置;
5)IteratorClient(客户端): 通过iterator 和 Aggregate 依赖子类;
编写程序展示一个学校系结构,需求如下:
要在一个页面中展示出学校的院系组成,一个学校有多少个学院,一个学院有多少个系;
--------计算机学院有以下专业-----------
Java工程师 数组
PHP专业
大数据工程师 ==>使用迭代器模式,兼容各种集合
-------信息工程学院有以下专业----------
网络信息安全 集合
电子技术
电子商务
1) 将学院看做是学校的子类,系是学院的子类, 这样实际上是依据组织大小进行分层的;
2) 我们实际要求是:在一个页面展示出学校的院系组成,一个学校有多少学院, 一个学院有多少系
3) 因此传统组织方案不利于遍历的实现;
1) 实例结构图
2) 相关代码实现
object IteratorClient {
@JvmStatic
fun main(args: Array) {
val collegeList = ArrayList()
val computerCollege = ComputerCollege()
val infoCollege = InfoCollege()
collegeList.add(computerCollege)
collegeList.add(infoCollege)
//从collageList 取出所有学院, Java中的List 已经实现了Iterator
val iterator = collegeList.iterator()
while (iterator.hasNext()) { //遍历所有的学院,然后输出各个学院的各个系
val college = iterator.next()//取出一个学院
println(college.getName())
val collegeIterator = college.createIterator()
while (collegeIterator.hasNext()) {
val department: Department = collegeIterator.next() as Department
println(department.name)
}
}
}
}
//学院接口
interface College {
fun getName():String //返回学院的名称
fun addDepartment(name:String,desc:String) //增加系
fun createIterator():Iterator //返回一个迭代器,遍历
}
//集合中的元素类型--系 Object
data class Department(val name:String, val desc:String)
//计算机学院
class ComputerCollege : College {
private var departments = arrayOfNulls(5)
var numOfDepartment: Int = 0 //保存当前数组的对象个数
init {
addDepartment("Java专业", "Java的专业")
addDepartment("PHP专业", "PHP的专业")
addDepartment("大数据专业", "大数据专业")
}
override fun getName(): String {
return "===========计算机学院==========="
}
override fun addDepartment(name: String, desc: String) {
val department = Department(name, desc)
departments[numOfDepartment] = department
numOfDepartment ++
}
override fun createIterator(): Iterator {
return ComputerCollegeIterator(departments)
}
}
//信息工程学院
class InfoCollege : College {
var departments: MutableList = ArrayList()
override fun getName(): String {
return "========信息工程学院========="
}
init {
departments = ArrayList()
addDepartment("网络信息安全","网络信息安全专业")
addDepartment("电子技术","电子技术专业")
addDepartment("电子商务","电子商务专业")
}
override fun addDepartment(name: String, desc: String) {
departments.add(Department(name, desc))
}
override fun createIterator(): Iterator {
return InfoCollegeIterator(departments)
}
}
//迭代器接口
interface Iterator {
fun hasNext(): Boolean
fun next():Any?
fun remove(e:Any?)
}
/**
* 计算机学院迭代器
* @param departments 这里我们需要声明计算机学院的Department, 是以Array的方式存放的
*/
class ComputerCollegeIterator(private val departments: Array?) : Iterator {
var index: Int = 0 //遍历的位置
//判断list是否还有下一个元素
override fun hasNext(): Boolean {
return departments?.let { it[index] } != null && index < departments.size
}
//取出下一个元素
override fun next(): Any? {
val department = departments?.let { it[index] }
index+=1
return department
}
override fun remove(e: Any?) {
TODO("Not yet implemented")
}
}
/**
* 信息工程学院迭代器
* @param departments 这里我们需要声明信息工程学院的Department, 是以List的方式存放的
*/
class InfoCollegeIterator(private val departments:List?) :Iterator {
var position: Int = 0 //遍历的位置
//判断是否还有下一个元素
override fun hasNext(): Boolean {
return position < departments?.size!!
}
//取出下一个元素
override fun next(): Any? {
val department = departments!![position]
position +=1
return department
}
override fun remove(e: Any?) {
TODO("Not yet implemented")
}
}
程序运行结果
===========计算机学院===========
Java专业
PHP专业
大数据专业
===========信息工程学院==========
网络信息安全
电子技术
电子商务
1.内部类Itr 充当具体实现迭代器Iterator 的类,作为ArrayList内部类;
2.List就是充当了聚合接口,含有一个Iterator() 方法, 返回一个迭代器对象;
3.ArrayList是实现聚合接口List的子类,实现了Iterator()方法
4.Iterator接口由系统提供;
5.迭代器模式解决了 不同集合(ArrayList linkedList) 统一遍历的问题;