1 输出院系结构的需求
在之前将的组合模式中提到了打印院系结构的需求,当时是采用组合模式实现的,现在我们用迭代器模式来实现一下。
2 迭代器模式介绍
迭代器模式(Iterator Pattern)也是一种常用的设计模式,属于行为性模式。如果我们的集合元素是用不同的方式实现的,有数组、集合、链表等,当客户端想要遍历这些集合元素的时候就要使用多种遍历方式,而且会暴露元素的内部结构。迭代器模式提供了一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合的底层表示。
角色分析:
1)Iterator:迭代器接口,包含hasNext、next、remove方法。
2)ConcreteIterator:迭代器实现类。
3)Aggregate:一个统一的聚合接口,将客户端和具体的元素解耦。
4)ConcreteAggregate:具体的聚合持有对象集合,并且提供一个返回迭代器的方法,该迭代器可以正确遍历集合。
5)Client:客户端类,通过Aggregate和Iterator进行遍历。
3 迭代器模式实现需求
首先由一个Department实体类:
public class Department {
private String name;
private String desc;
public Department(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
数学学院的迭代器实现类:
public class MathCollegeIterator implements Iterator {
// 确定Department是以什么方式存放
private Department[] departments;
// 遍历的位置
private int position = 0;
public MathCollegeIterator(Department[] departments) {
this.departments = departments;
}
@Override
public boolean hasNext() {
return position < departments.length && departments[position] != null;
}
@Override
public Object next() {
Department department = departments[position];
position++;
return department;
}
@Override
public void remove() {
}
}
物理学院的迭代器实现类:
public class PhysicsCollegeIterator implements Iterator {
// 物理学院是以List形式存放系
private List<Department> departmentList;
// 索引
private int index = -1;
public PhysicsCollegeIterator(List<Department> departmentList) {
this.departmentList = departmentList;
}
@Override
public boolean hasNext() {
return index < departmentList.size() - 1;
}
@Override
public Object next() {
index++;
return departmentList.get(index);
}
@Override
public void remove() {
}
}
学院的抽象类(对应到Aggregate):
public interface College {
String getName();
// 添加系
void addDepartment(String name, String desc);
// 创建迭代器
Iterator createIterator();
}
数学学院MathCollege:
public class MathCollege implements College {
private Department[] departments;
// 保存当前数组的对象个数
private int numberOfDepartment = 0;
public MathCollege() {
departments = new Department[5];
addDepartment("高等数学", "树上挂了好多人");
addDepartment("线性代数", "矩阵是个什么东西");
addDepartment("概率统计", "博彩分析师");
}
@Override
public String getName() {
return "数学学院";
}
@Override
public void addDepartment(String name, String desc) {
departments[numberOfDepartment] = new Department(name, desc);
numberOfDepartment++;
}
@Override
public Iterator createIterator() {
return new MathCollegeIterator(departments);
}
}
物理学院PhysicsCollege:
public class PhysicsCollege implements College {
private List<Department> departmentList;
public PhysicsCollege() {
departmentList = new ArrayList<>();
addDepartment("理论力学", "牛顿的棺材板压不住了");
addDepartment("量子力学", "上帝天天玩骰子");
addDepartment("电动力学", "天才的麦克斯韦");
addDepartment("热力学", "变与不变之道");
}
@Override
public String getName() {
return "物理学院";
}
@Override
public void addDepartment(String name, String desc) {
departmentList.add(new Department(name, desc));
}
@Override
public Iterator createIterator() {
return new PhysicsCollegeIterator(departmentList);
}
}
为了Client端调用方便,我们写了一个OutputImpl类:
public class OutputImpl {
// 学院集合
private List<College> collegeList;
public OutputImpl(List<College> collegeList) {
this.collegeList = collegeList;
}
// 遍历所有学院,然后调用printDepartment输出各个学院的系
public void printCollege() {
Iterator<College> iterator = collegeList.iterator();
while (iterator.hasNext()) {
College college = iterator.next();
System.out.println("==========" + college.getName() + "==========");
printDepartment(college.createIterator());
}
}
// 学院输出系
public void printDepartment(Iterator iterator) {
while (iterator.hasNext()) {
Department department = (Department) iterator.next();
System.out.println(department.getName());
}
}
}
Client调用:
public class Client {
public static void main(String[] args) {
// 创建学院
List<College> collegeList = new ArrayList<>();
collegeList.add(new MathCollege());
collegeList.add(new PhysicsCollege());
OutputImpl output = new OutputImpl(collegeList);
output.printCollege();
}
}
输出结果:
==========数学学院==========
高等数学
线性代数
概率统计
==========物理学院==========
理论力学
量子力学
电动力学
热力学
4 迭代器模式的特点
1)迭代器模式提供了一个统一的遍历对象的方法,调用方不需要再考虑聚合的类型,使用一种方法就可以遍历对象了。
2)隐藏了聚合的内部结构,调用方要遍历聚合时只能取迭代器,而不会知道聚合的具体组成。
3)满足单一职责原则,即一个类只有一个引起变化的原因。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,那么如果集合改变了,只影响到聚合的对象,而遍历方式改变的话,只影响迭代器。
4)每个聚合对象都需要一个迭代器,会产生多个迭代器以至于不好管理。