迭代器模式
现在有一个数据容器,里面存储着一个数据集合,如果要访问这个容器,则必然要对它进行遍历。可以把遍历、添加数据、数据的逻辑写在容器对象中,容器再提供一个遍历方法的接口。但是这样的设计不符合单一职责原则,一旦集合里面的数据量变大便难以维护。或者容器不实现遍历方法,由访问者实现,这样会导致容器内部的逻辑被公开,不符合封装原则。这时便要使用迭代器模式。
迭代器模式的核心思想是让每一个数据容器提供一个遍历访问该容器的迭代器从而方便外部的访问。其主要工作是在容器的迭代器中实现遍历的逻辑,在容器中提供一个拿到迭代器的公开方法。这里记录一个书上的例子来说明。
有一个公司要统计记录员工的信息。这里使用迭代器模式来实现这个业务
一、创建员工类Employee
public class Employee {
private String name;
private String age;
private String position;
@Override
public String toString() {
return name+","+age+","+position;
}
public Employee(String name, String age, String position) {
this.name = name;
this.age = age;
this.position = position;
}
}
这里简单的将员工信息设置为姓名,年龄,职位这三个,并提供一个toString()方法打印员工信息
二、新建一个迭代器接口Iterator<>
public interface Iterator<T> {//这里的泛型传要遍历的集合的元素类型
boolean hasNext();// 判断是否还有下一个
T next();//拿到下一个元素
}
在这个迭代器接口中定义了两个方法,hasNext方法用来判断是否还有下一个,next方法则是拿到下一个元素。如果一个容器要提供迭代功能,就要有一个实现了该接口的迭代器。
三、新建一个MyIterator类
public class MyIterator implements Iterator<Employee> {
private List<Employee> list;
private int position;
public MyIterator(List<Employee> list) {
this.list = list;
position=0;
}
@Override
public boolean hasNext() {
return position<list.size();
}
@Override
public Employee next() {
return list.get(position++);
}
}
这里的新建了一个迭代器接口的实现类,这个就是数据容器的迭代器类,通过构造器传入数据集合,内部维护一个int型的下标从而实现对集合的遍历。
四、新建一个数据容器接口Container<>
public interface Container<T> {//这里的泛型传要遍历的集合的元素类型
void add(T t);//增加元素
void remove(T t);//移除元素
Iterator<T> getIterator();//拿到迭代器
}
这里提供了一个数据容器的接口,并提供了增加,删除数据的方法和一个拿到迭代器的方法,拿到迭代器便可以实现查找的功能等等。
五、新建一个MyCompany 类
public class MyCompany implements Container<Employee> {
private List<Employee> list;
public MyCompany(){
list=new ArrayList<>();
init();
}
@Override
public void add(Employee employee) {
list.add(employee);
}
@Override
public void remove(Employee employee) {
list.remove(employee);
}
@Override
public Iterator<Employee> getIterator() {
return new MyIterator(list);
}
private void init(){
list.add(new Employee("Jack","30","teacher"));
list.add(new Employee("Mick","21","stuff"));
list.add(new Employee("Jane","40","boss"));
}
}
这里的MyCompany类就是数据容器,实现了数据容器的接口,为了方便测试直接在构造器中初始化几个数据。
新建Client测试类
public class Client {
public static void main(String[] args){
Container company=new MyCompany();
Iterator iterator=company.getIterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
首先拿到容器的一个实例,然后拿到容器的Iterator,然后通过Iterator来实现对容器数据集合的遍历
。输出结果如下
"C:\Program Files\Java\jdk-10.0.2\bin\java.exe" "-javaagent:E:\IntelliJ IDEA\IntelliJ IDEA 2018.3.5\lib\idea_rt.jar=38508:E:\IntelliJ IDEA\IntelliJ IDEA 2018.3.5\bin" -Dfile.encoding=UTF-8 -classpath F:\program\Java\myProject\IteratorTest\out\production\IteratorTest com.xiaogege.Client
Jack,30,teacher
Mick,21,stuff
Jane,40,boss
Process finished with exit code 0
正如书中所说,一般不需要我们手动实现一个迭代器,一般的语言内部都实现了迭代器,但是我们仍然需要了解这种设计模式。