设计模式(十一):迭代器模式
一、概述
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
二、解决问题
迭代器模式就是提供一种遍历元素的统一接口,用一致的方法遍历聚合元素。试想,如果我们的聚合元素是用不同的方式实现的,有些用了数组,有些用了java的集合类,或者还有其他方式,当客户端要遍历这些元素的时候就要使用多种遍历方式,而且还会暴露元素的内部结构。
三、应用实例
下面我用一个在页面展示一个学校院系结构的例子来讲解迭代器的用法,讲完例子后我们再来看看迭代器的结构类图。现在我们的需求是这样,要在一个页面中展示出学校的院系组成,它应该是树状结构的,一个学校有多个学院,一个学院有多个系。当然了,页面的具体代码就不写了,我们就来分析后台的实现方法。
前面学了面向接口编程,我们现在可以把学院抽象出来做成一个接口,设定里面方法有getName,addDepartment(增加一个系),一个可以遍历全部系的方法(暂且取名为CreateIterator,就是返回一个迭代器的方法)。看看接口的代码实现
package com.jet.someinterface; import java.util.Iterator; /** * Created by Administrator on 2016/11/14. */ public interface College { public String getName(); /** * 增加一个系的方法 */ public void addDepartment(String name,String description); /** *返回一个迭代器用来遍历每一个系 */ public Iterator createIterator(); }
学院下面的是专业,我们把专业的对象创建出来
package com.jet.com.jet.vo; /** * Created by Administrator on 2016/11/14. * description:专业对象 */ public class DepartmentVo { private String name; private String description; public DepartmentVo(String name, String description) { this.name = name; this.description = description; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
创建第一学院对象(计算机学院),及其对应的迭代器
package com.jet.impl; import com.jet.com.jet.vo.DepartmentVo; import com.jet.someinterface.College; import java.util.Iterator; /** * Created by Administrator on 2016/11/14. * description:计算机学院 */ public class ComputerCollege implements College{ DepartmentVo[] departmentVos;//用来放置专业对象,注意这里用的是数组 int numberOfDepartments = 0;//保存当前数组已有对象数 static final int MAX_DEPARTMENTS = 4;//控制专业数组大小 public String getName() { return "计算机学院"; } public ComputerCollege() { departmentVos = new DepartmentVo[MAX_DEPARTMENTS]; addDepartment("计算机科学与技术","计算机科学与技术"); addDepartment("软件工程 ","软件工程 "); addDepartment("网络工程","网络工程"); addDepartment("信息安全","信息安全"); } public void addDepartment(String name,String description) { if(numberOfDepartments >= MAX_DEPARTMENTS){ System.out.println("已超过学院最专业数限制,不能添加专业了!"); }else{ DepartmentVo departmentVo = new DepartmentVo(name,description); departmentVos[numberOfDepartments] = departmentVo; numberOfDepartments = numberOfDepartments + 1; } } public Iterator createIterator() { //返回一个遍历器 return new ComputerCollegeIterator(departmentVos); } }
package com.jet.impl; import com.jet.com.jet.vo.DepartmentVo; import java.util.Iterator; /** * Created by Administrator on 2016/11/14. * decription:计算机学院的遍历器,我们这里是实现了java自带的便利器Iterator */ public class ComputerCollegeIterator implements Iterator{ DepartmentVo[] departmentVos; int position = 0;//遍历的位置 public ComputerCollegeIterator(DepartmentVo[] departmentVos) { this.departmentVos = departmentVos; } public boolean hasNext() { if(position >= departmentVos.length || departmentVos[position] == null ){ return false; }else{ return true; } } public Object next() { DepartmentVo departmentVo = departmentVos[position]; position = position + 1; return departmentVo; } //删除的方法我们暂时不实现 public void remove() { } }
创建第二个学院(信息工程学院)及其迭代器
package com.jet.impl; import com.jet.com.jet.vo.DepartmentVo; import com.jet.someinterface.College; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Created by Administrator on 2016/11/14. * description:信息工程学院 */ public class InfoEngineeringCollege implements College{ List<DepartmentVo> departmentVoList;//注意这里我们使用了集合来放置专业对象了 public String getName() { return "信息工程学院"; } public InfoEngineeringCollege() { this.departmentVoList = new ArrayList<DepartmentVo>(); addDepartment("电子信息工程","电子信息工程"); addDepartment("信息工程","信息工程"); addDepartment("通信工程","通信工程"); } public void addDepartment(String name, String description) { DepartmentVo departmentVo = new DepartmentVo(name,description); departmentVoList.add(departmentVo); } public Iterator createIterator() { return new InfoEngineeringCollengIterator(departmentVoList); } }
package com.jet.impl; import com.jet.com.jet.vo.DepartmentVo; import java.util.Iterator; import java.util.List; /** * Created by Administrator on 2016/11/14. * description:信息工程学院迭代器 */ public class InfoEngineeringCollengIterator implements Iterator{ int index = 0; List<DepartmentVo> departmentVoList; public InfoEngineeringCollengIterator(List<DepartmentVo> departmentVoList) { this.departmentVoList = departmentVoList; } public boolean hasNext() { if(index >= departmentVoList.size() ){ return false; }else { index = index + 1; return true; } } public Object next() { return departmentVoList.get(index); } public void remove() { } }
创建数据输出类(也就是客户端)
package com.jet.impl; import com.jet.com.jet.vo.DepartmentVo; import com.jet.someinterface.College; import java.util.Iterator; import java.util.List; /** * Created by Administrator on 2016/11/15. * description:模拟向页面输出院系信息的类,该类负责遍历每个专业并打印其信息 */ public class OutputInfoImpl { //学院集合 List<College> collegeList; public OutputInfoImpl(List<College> collegeList) { this.collegeList = collegeList; } public void printDepartement(){ //java的集合实现了迭代器,可以直接调用方法取到 Iterator departmentIterator = collegeList.iterator(); while (departmentIterator.hasNext()){ College college = (College) departmentIterator.next(); System.out.println("--------" + college.getName() + "有以下专业-----------"); printDepartment(college.createIterator()); } } public void printDepartment(Iterator iterator){ while (iterator.hasNext()){ DepartmentVo departmentVo = (DepartmentVo) iterator.next(); System.out.println(departmentVo.getName()); } } }
测试迭代器
package com.jet.test; import com.jet.impl.ComputerCollege; import com.jet.impl.InfoEngineeringCollege; import com.jet.impl.OutputInfoImpl; import com.jet.someinterface.College; import java.util.ArrayList; import java.util.List; /** * Created by Administrator on 2016/11/15. * description:测试迭代器 */ public class IteratorTest { public static void main(String[] args) { //创建学院集合 List<College> collegeList = new ArrayList<College>(); College computerCollege = new ComputerCollege(); College infoEngineeringCollege = new InfoEngineeringCollege(); collegeList.add(computerCollege); collegeList.add(infoEngineeringCollege); OutputInfoImpl outputInfo = new OutputInfoImpl(collegeList); outputInfo.printDepartement(); } }
测试结果:
四、结构类图
五、使用场景
当要展示一组相似对象,或者遍历一组相同对象时使用。
六、优缺点
1、优点
(1)、提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。
(2)、隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成。
(3)、提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。而如果遍历方式改变的话,只影响到了迭代器。
2、缺点
每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类。