1、院系结构
编写程序展示一个学校院系结构:
- 需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系。如图:
2、传统方式问题
-
将学院看做是学校的子类,系是学院的子类,这样实际上是站在组织大小来进行分层次的
-
实际上我们的要求是:
- 在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系,
- 因此这种方案,不能很好实现的遍历的操作
-
解决方案 => 迭代器模式
3、基本介绍
-
迭代器模式(
lterator Pattern
)是常用的设计模式,属于行为型模式 -
如果我们的 集 合 元 素 是 用 不 同 的 方 式 实 现 \color{red}集合元素是用不同的方式实现 集合元素是用不同的方式实现的,有数组,还有
java
的集合类,或者还有其他方式,- 当客户端要遍历这些集合元素的时候就要使用多种遍历方式,而且还会暴露元素的内部结构,
- 可以考虑使用迭代器模式解决。
-
迭代器模式,提供一种遍历集合元素的统一接口,
- 用一致的方法遍历集合元素,不需要知道集合对象的底层表示,
- 即:不暴露其内部的结构。
4、原理类图
5、案例解决
组合+迭代器模式;
public class Client {
public static void main(String[] args) {
//创建大学
OrganizationComponent<University> university = new University<>("u1", "u1");
//创建学院
university.add(new College<>("数统","数统"));
Iterator<OrganizationComponent> iterator = university.createIterator();
while (iterator.hasNext()) {
OrganizationComponent next = iterator.next();
Iterator<OrganizationComponent> iterator1 = next.createIterator();
System.out.println("=========");
System.out.println(next.name() + " " + next.des());
System.out.println("=========");
while (iterator1.hasNext()){
OrganizationComponent next1 = iterator1.next();
System.out.println(next1.name() + " " + next1.des());
}
}
}
/*
=========
c1 c1
=========
d1 d1
d2 d2
d3 d3
d4 d4
d5 d5
=========
c2 c2
=========
d1 d1
d2 d2
d3 d3
d4 d4
d5 d5
=========
数统 数统
=========
d1 d1
d2 d2
d3 d3
d4 d4
d5 d5
*/
}
public abstract class OrganizationComponent<E> {
private String name;//名字
private String des;//说明
protected void add(OrganizationComponent<E> component) {
//默认实现,叶子节点不需要重写add方法
throw new UnsupportedOperationException();
}
protected void remove(OrganizationComponent<E> component) {
//默认实现,叶子节点不需要重写remove方法
throw new UnsupportedOperationException();
}
//==============================
protected <T> Iterator<T> createIterator(){
throw new UnsupportedOperationException();
}
public OrganizationComponent(String name, String des) {
this.name = name;
this.des = des;
}
public String name() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String des() {
return des;
}
public void setDes(String des) {
this.des = des;
}
}
//University 就是 Composite,可以管理College
public class University<E> extends OrganizationComponent<E> {
//存放的是College
List<OrganizationComponent<E>> components = new ArrayList<>();
public University(String name, String des) {
super(name, des);
//假设在这里创建了学院
components.add(new College<>("c1","c1"));
components.add(new College<>("c2","c2"));
}
// 重写add
@Override
protected void add(OrganizationComponent<E> component) {
/// 将来实际业务中,University 的 add 和 College 的 add 不一定完全一样
components.add(component);
}
//重写remove
@Override
protected void remove(OrganizationComponent<E> component) {
components.remove(component);
}
//========================
@Override
protected Iterator<OrganizationComponent<E>> createIterator() {
return new UniversityIterator<>(components);
}
}
//校
public class UniversityIterator<E> implements Iterator<E> {
List<E> departmentList;//大学是以List的方式存放院
int index = -1;//索引
public UniversityIterator(List<E> departmentList) {
this.departmentList = departmentList;
}
//判断list中还有没有下一个元素
@Override
public boolean hasNext() {
return index < departmentList.size() - 1;
}
@Override
public E next() {
index++;
return departmentList.get(index);
}
}
public class College<E> extends OrganizationComponent<E> {
//存放的是"子"对象
OrganizationComponent<E>[] components ;
public College(String name, String des) {
super(name, des);
components = new Department[5];
//假设在这里创建了系部
add(new Department("d1","d1"));
add(new Department("d2","d2"));
add(new Department("d3","d3"));
add(new Department("d4","d4"));
add(new Department("d5","d5"));
}
int index = 0;
// 重写add
@Override
protected void add(OrganizationComponent<E> component) {
components[index] = component;
index++;
}
//重写remove
@Override
protected void remove(OrganizationComponent<E> component) {
//...
}
//==============================
@Override
protected Iterator<OrganizationComponent<E>> createIterator() {
return new CollegeIterator<E>(components);
}
}
//院系
public class CollegeIterator<E> implements Iterator<OrganizationComponent<E>> {
OrganizationComponent<E>[] elementList;
int position = -1;//索引
public CollegeIterator(OrganizationComponent<E>[] departmentList) {
this.elementList = departmentList;
}
//判断list中还有没有下一个元素
@Override
public boolean hasNext() {
return position < elementList.length - 1;
}
@Override
public OrganizationComponent<E> next() {
position++;
return elementList[position];
}
}
6、迭代器模式-ArrayList源码
- 内部类
Itr
:充当具体实现迭代器Iterator
的类,作为ArrayList
的内部类 List
:充当了聚合接口,含有一个iterator() 方法,返回一个迭代器对象ArrayList
:是实现聚合接口List
的子类,实现类iterator()
Iterator
:接口系统提供- 迭代器模式解决了 不同集合(
ArrayList
,LinkedList
)统一遍历问题
7、迭代器模式的注意事项与细节
优点
-
提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。
-
隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成。
-
提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做 单 一 责 任 原 则 \color{red}单一责任原则 单一责任原则)。
- 在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,
- 这样一来集合改变的话,只影响到聚合对象。而如果遍历方式改变的话,只影响到了迭代器。
-
当要展示一组相似对象,或者遍历一组相同对象时使用,适合使用迭代器模式
缺点
- 每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类