迭代器模式又称为游标模式,主要作用是访问容器,比如java中的List, map, 数组等,我们知道对容器对象的访问必然会设计遍历,如果我们遍历的方法写在容器中,对于容器来说就承载了过多功能,如果然使用者自己实现迭代这个过程,就会使得代码逻辑复杂,正是这样,迭代模式应运而生.
迭代器模式在客户访问类和容器体之间插入一个第三者—迭代器,很好地解决了上面提到的弊端.
它的uml图如下:
image.png
通过实现迭代器Iterator接口去访问遍历容器里面内容,从而避免
1,遍历的方法写在容器中,对于容器来说就承载了过多功能
2,使用者自己实现迭代这个过程,就会使得代码逻辑复杂
下面一个简单示范,如何使用迭代器模式去重构一个未使用迭代器模式而代码臃肿的案例
需求很简单,目前小明的部门和小辉的部门需要去回报部门内员工情况给老板, 这个汇报过程就是一个遍历,刚开始我不去使用迭代器模式实现,如下:
public class Employee {
public String name; //姓名
public int age; //年龄
public String sex; //性别
public String position; //职位
public Employee(String name, int age, String sex, String position) {
this.name = name;
this.age = age;
this.sex = sex;
this.position = position;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", position='" + position + '\'' +
'}';
}
}
public class CompanyMin {
private List<Employee> list = new ArrayList<>();
public CompanyMin(){
list.add(new Employee("小民",96,"男","程序员"));
list.add(new Employee("小芸",22,"女","测试"));
list.add(new Employee("小方",18,"女","测试"));
list.add(new Employee("可儿",21,"女","设计"));
}
public List<Employee> getEmployees(){
return list;
}
}
public class CompanyHui {
private Employee[] array = new Employee[3];
public CompanyHui(){
array[0] = new Employee("辉哥",108,"男","程序员");
array[1] = new Employee("龙哥",78,"男","程序员");
array[2] = new Employee("白哥",88,"男","程序员");
}
public Employee[] getEmployee(){
return array;
}
}
public static void main(String[] args){
CompanyMin companyMin = new CompanyMin();
List<Employee> employeesMin = companyMin.getEmployees();
for (Employee employee : employeesMin){
System.out.println(employee.toString());
}
CompanyHui companyHui = new CompanyHui();
Employee[] employeesHui = companyHui.getEmployee();
for (Employee employee : employeesHui){
System.out.println(employee.toString());
}
}
这样写其实也没啥功能上面问题 ,就是如果在这里再增加一个部门,势必会再添加迭代逻辑, 这样的做法肯定不太科学, 我们需要使用迭代器模式对它进行重构.
首先创建一个迭代器接口:
public interface Iterator {
/**
* 是否有下一个元素
* @return true表示有,false表示没有
*/
boolean hasNext();
Object next();
}
public class MinIterator implements Iterator{
private List<Employee> list;
private int position;
public MinIterator(List<Employee> list) {
this.list = list;
}
@Override
public boolean hasNext() {
return !(position > list.size() - 1 || list.get(position) == null);
}
@Override
public Object next() {
Employee employee = list.get(position);
position++;
return employee;
}
}
public class HuiIterator implements Iterator{
private Employee[] array;
private int position;
public HuiIterator(Employee[] array) {
this.array = array;
}
@Override
public boolean hasNext() {
return !(position > array.length - 1 || array[position] == null);
}
@Override
public Object next() {
Employee e = array[position];
position++;
return e;
}
}
再创建容器接口,和实现容器类
public interface Company {
/**
* 返回一个迭代器对象
*/
Iterator iterator();
}
public class CompanyMin implements Company{
private List<Employee> list = new ArrayList<>();
public CompanyMin(){
list.add(new Employee("小民",96,"男","程序员"));
list.add(new Employee("小芸",22,"女","测试"));
list.add(new Employee("小方",18,"女","测试"));
list.add(new Employee("可儿",21,"女","设计"));
}
public List<Employee> getEmployees(){
return list;
}
@Override
public Iterator iterator() {
return new MinIterator(list);
}
}
public class CompanyHui implements Company{
private Employee[] array = new Employee[3];
public CompanyHui(){
array[0] = new Employee("辉哥",108,"男","程序员");
array[1] = new Employee("龙哥",78,"男","程序员");
array[2] = new Employee("白哥",88,"男","程序员");
}
public Employee[] getEmployee(){
return array;
}
@Override
public Iterator iterator() {
return new HuiIterator(array);
}
}
public static void main(String[] args){
CompanyHui companyHui = new CompanyHui();
check(companyHui.iterator());
CompanyMin companyMin = new CompanyMin();
check(companyMin.iterator());
}
private static void check(Iterator iterator){
while (iterator.hasNext()){
System.out.println(iterator.next().toString());
}
}
最后的调用的确是更加简洁清晰了.
Android中的迭代器模式
在Android中Cursor接口就是使用的迭代器模式, 它可以去遍历查找数据库(SQLite)中的表项,在这里Cursor充当的是Iterator, 数据库相当于一个容器。
总结:对于迭代模式来说,其自身优点很明显也很单一,支持以不同的方式去遍历一个容器对象,也可以有多个遍历,弱化了容器类与遍历算法之间的关系。
网友评论