分析影响网站排名的因素,销售推广,互联网三网合一网站建设,甘特图模板关于网站建设一、介绍
迭代器模式#xff08;Iterator Pattern#xff09;又称为游标#xff08;Cursor#xff09;模式#xff0c;是行为型设计模式之一。迭代器模式算是一个比较古老的设计模式#xff0c;其源于对容器的访问#xff0c;比如Java中的List、Map、数组等#xff0c…一、介绍
迭代器模式Iterator Pattern又称为游标Cursor模式是行为型设计模式之一。迭代器模式算是一个比较古老的设计模式其源于对容器的访问比如Java中的List、Map、数组等我们知道对容器对象的访问必然会涉及遍历算法我们可以将遍历的方法封装在容器中或者不提供遍历方法。如果我们将遍历的方法封装到容器中那么对于容器类来说就承担了过多的功能容器类不仅要维护自身内部的数据元素而且还要对外提供遍历的接口方法因为遍历状态的存储问题还不能对同一个容器同时进行多个遍历操作如果我们不提供遍历方法而让使用者自己去实现又会让容器的内部细节暴露无遗正因于此迭代模式应运而生在客户访问类与容器体之间插入了一个第三者——迭代器很好地解决了上面所述的弊端。
二、定义
提供一种方法顺序访问一个容器对象中的各个元素而又不需要暴露该对象的内部表示。
三、使用场景
遍历一个容器对象。
四、迭代器模式的UML类图
UML类图 通用模式代码
迭代器接口
public interface IteratorT {/*** 是否还有下一个元素* return true表示有false表示没有**/boolean hasNext();/*** 返回当前位置的元素并将位置移至下一位**/T next();
}
具体迭代器类
public class ConcreteIteratorT implements IteratorT{private ListT list;private int cursor 0;public ConcreteIterator(ListT list) {this.list list;}Overridepublic boolean hasNext() {return cursor ! list.size();}Overridepublic T next() {T obj null;if (this.hasNext()) {obj this.list.get(cursor);}return obj;}
}
容器接口
public interface AggregationT {/*** 添加一个元素**/void add(T obj);/*** 移除一个元素**/void remove(T obj);/*** 获取容器的迭代器**/IteratorT iterator();
}
具体容器类
public class ConcreteAggregationT implements AggregationT{private ListT list new ArrayList();Overridepublic void add(T obj) {list.add(obj);}Overridepublic void remove(T obj) {list.remove(obj);}Overridepublic IteratorT iterator() {return new ConcreteIterator(list);}
}
客户类
public class Client {public static void main(String args[]) {AggregationString a new ConcreteAggregation();a.add(a);a.add(b);a.add(c);IteratorString iterator a.iterator();while (iterator.hasNext()) {System.out.print(iterator.next());}}
}
角色介绍
Iterator迭代器接口迭代器接口负责定义、访问和遍历元素的接口。ConcreteIterator具体迭代器类具体迭代器类的目的主要是实现迭代器接口并记录遍历的当前位置。Aggregate容器接口容器接口负责提供创建具体迭代器角色的接口。ConcreteAggregate具体容器类具体迭代器角色与该容器相关联。Client客户类。
五、简单实现
小民和小辉分别在公司的两个事业部某天老板安排任务让他们俩统计一下各自部门的员工数据这很好办嘛建一个类用数据结构把所有员工数据存进去即可老板要看的时候给他用for循环实现还是比较容易的下面就先为员工创建一个实体类
员工实体类
public class Employee {private String name;// 姓名private int age;// 年龄private String sex;// 性别private String position;// 职位public Employee(String name, int age, String sex, String position) {super();this.name name;this.age age;this.sex sex;this.position position;}// 简化代码省略setter和getter方法Overridepublic String toString() {return Employee{ name name \ , age age , sex sex , position position \ };}
}
小民部门
public class CompanyMin {private ListEmployee list new ArrayList();public CompanyMin(){list.add(new Employee(小民, 26, 男, 程序猿));list.add(new Employee(小芸, 22, 女, 测试));list.add(new Employee(小方, 18, 女, 测试));list.add(new Employee(可儿, 21, 女, 设计));list.add(new Employee(朗情, 19, 女, 设计)); //吐槽一下为什么就小民一个男的小辉部门全男的。}public ListEmployee getEmployees(){return list;}
}
小辉部门
public class CompanyHui {private Employee[] array new Employee[3];public CompanyHui(){array[0] new Employee(辉哥, 28, 男, 程序猿);array[1] new Employee(小红, 23, 男, 程序猿);array[2] new Employee(小辉, 25, 男, 程序猿);}public Employee[] getEmployees(){return array;}
}
可见小民和小辉的内部实现是两种方式小民的人员信息容器的内部实质是使用的一个List类存储人员信息而小辉的实质上使用的是一个数组如果老板要查看人员信息就必须遍历两个容器
Boss查看
public class Boss {public static void main(String[] args) {CompanyHui hui new CompanyHui();Employee[] huiList hui.getEmployees();for(int i 0; i huiList.length; i){System.out.println(huiList[i]);}CompanyMin min new CompanyMin();List minList min.getEmployees();for(int i 0; i minList.size(); i){System.out.println(minList.get(i).toString());}}
}
结果
Employee{name辉哥, age28, sex男, position程序猿}
Employee{name小红, age23, sex男, position程序猿}
Employee{name小辉, age25, sex男, position程序猿}
Employee{name小民, age26, sex男, position程序猿}
Employee{name小芸, age22, sex女, position测试}
Employee{name小方, age18, sex女, position测试}
Employee{name可儿, age21, sex女, position设计}
Employee{name朗情, age19, sex女, position设计}
这样看似也没有问题但是如果有多个部门每个部门有各自的实现那么我们就要在Boss类中增加一遍遍历逻辑这样Boss类的功能会越来越多同时暴露了内部细节。那么我们需要定义一个迭代器接口
public interface Iterator {/*** 是否还有下一个元素 * * return true表示有false表示没有*/boolean hasNext();/*** 返回当前元素并将位置移至下一位*/Object next();
}
小民的迭代器
public class MinIterator implements Iterator{private ListEmployee list;private int position;public MinIterator(ListEmployee list){this.list list;}Overridepublic boolean hasNext() {return !(position list.size() - 1 || list.get(position) null);}Overridepublic Object next() {Employee e list.get(position);position;return e;}}
小辉的迭代器
public class HuiIterator implements Iterator{private Employee[] array;private int position;public HuiIterator(Employee[] array){this.array array;}Overridepublic boolean hasNext() {return !(position array.length - 1 || array[position] null);}Overridepublic Object next() {Employee e array[position];position;return e;}}
定义容器类的接口
public interface Company {/*** 返回一个迭代器对象* * return 迭代器对象*/Iterator iterator();}
修改一下之前的两个容器类
public class CompanyHui implements Company{private Employee[] array new Employee[3];public CompanyHui(){array[0] new Employee(辉哥, 28, 男, 程序猿);array[1] new Employee(小红, 23, 男, 程序猿);array[2] new Employee(小辉, 25, 男, 程序猿);}public Employee[] getEmployees(){return array;}Overridepublic Iterator iterator() {return new HuiIterator(array);}
}
public class CompanyMin implements Company{private ListEmployee list new ArrayList();public CompanyMin(){list.add(new Employee(小民, 26, 男, 程序猿));list.add(new Employee(小芸, 22, 女, 测试));list.add(new Employee(小方, 18, 女, 测试));list.add(new Employee(可儿, 21, 女, 设计));list.add(new Employee(朗情, 19, 女, 设计));}public ListEmployee getEmployees(){return list;}Overridepublic Iterator iterator() {return new MinIterator(list);}
}
Boss查看
public class Boss {public static void main(String[] args) {CompanyHui hui new CompanyHui();check(hui.iterator());CompanyMin min new CompanyMin();check(min.iterator());}private static void check(Iterator iterator){while (iterator.hasNext()) {System.out.println(iterator.next().toString());}}
}
六、Android源码中的迭代器模式
1、Cursor
当我们使用SQLiteDatabase的query方法查询数据库时会返回一个Cursor游标对象该游标的实质就是一个具体的迭代器我们可以使用它来遍历数据库查询所得的结果集。
七、总结
迭代器模式发展至今几乎所有的高级语言都有相应的内置实现对于开发者而言已经极少会自己去实现迭代器了所以本章内容更多的是了解而非应用。
优点
符合面向对象设计原则中的单一职责原则。支持对容器对象的多种遍历。弱化了容器类与遍历算法之间的关系。
缺点
类文件的增加。会出现ConcurrentModificationException异常。遍历过程是一个单向且不可逆的遍历。