1 初识迭代器模式:
定义:提供一种方法来顺序访问一个集合对象中的各个元素,而又不需要暴露该对象的内部表示
结构:
注意: 具体集合是放在迭代器实现类内,作为属性和迭代器实现关联, 具体集合仅仅作为一个数据集的作用,迭代器则对数据如何取,内部增加什么过滤或者算法,来实现对具体集合数据的操作,
你可以理解 集合是原木, 迭代器是木匠,木匠可以通过自己的手法(算法)来对原木进行全部获取或者雕刻成什么作品来部分获取
参考实现:
迭代器模式调用流程图:
使用数组作为基础集合数据来模拟迭代器代码部分:
客户端:
public class Client {
public void someOperation(){
String[] names = {"张三","李四","王五"};
Aggregate aggregate = new ConcreteAggregate(names);
Iterator it = aggregate.createIterator();
//首先设置迭代器到第一个元素
it.first();
while(!it.isDone()){
Object obj = it.currentItem();
System.out.println("the obj=="+obj);
it.next();
}
}
public static void main(String[] args) {
Client client = new Client();
client.someOperation();
}
}
集合接口:
public abstract class Aggregate {
/**
* 工厂方法,创建相应迭代器对象的接口
* @return 相应迭代器对象的接口
*/
public abstract Iterator createIterator();
}
集合实现类:
public class ConcreteAggregate extends Aggregate {
/**
* 示意,表示聚合对象具体的内容
*/
private String[] ss = null;
/**
* 构造方法,传入聚合对象具体的内容
* @param ss 聚合对象具体的内容
*/
public ConcreteAggregate(String[] ss){
this.ss = ss;
}
public Iterator createIterator() {
//实现创建Iterator的工厂方法
return new ConcreteIterator(this);
}
/**
* 获取索引所对应的元素
* @param index 索引
* @return 索引所对应的元素
*/
public Object get(int index){
Object retObj = null;
if(index < ss.length){
retObj = ss[index];
}
return retObj;
}
/**
* 获取聚合对象的大小
* @return 聚合对象的大小
*/
public int size(){
return this.ss.length;
}
}
迭代器接口:
public interface Iterator {
/**
* 移动到聚合对象的第一个位置
*/
public void first();
/**
* 移动到聚合对象的下一个位置
*/
public void next();
/**
* 判断是否已经移动聚合对象的最后一个位置
* @return true表示已经移动到聚合对象的最后一个位置,
* false表示还没有移动到聚合对象的最后一个位置
*/
public boolean isDone();
/**
* 获取迭代的当前元素
* @return 迭代的当前元素
*/
public Object currentItem();
}
迭代器实现类:
public class ConcreteIterator implements Iterator {
/**
* 持有被迭代的具体的聚合对象
*/
private ConcreteAggregate aggregate;
/**
* 内部索引,记录当前迭代到的索引位置。
* -1表示刚开始的时候,迭代器指向聚合对象第一个对象之前
*/
private int index = -1;
/**
* 构造方法,传入被迭代的具体的聚合对象
* @param aggregate 被迭代的具体的聚合对象
*/
public ConcreteIterator(ConcreteAggregate aggregate) {
this.aggregate = aggregate;
}
public void first(){
index = 0;
}
public void next(){
if(index < this.aggregate.size()){
index = index + 1;
}
}
public boolean isDone(){
if(index == this.aggregate.size()){
return true;
}
return false;
}
public Object currentItem(){
return this.aggregate.get(index);
}
}
2 体会迭代器模式:
场景问题: 以一个统一方式来访问内部实现不同的聚合对象(子母公司合作统计工资模块案例)
不使用模式的解决方案: 代码重写,统一成同样实现方式
使用模式的解决方案: 如上图,不同模块因为使用不同具体实现,使用迭代器模式,将原来两个不同的数据
最后用相同的输出框架给框起来。达到统一输出的目的;
下面案例调用流程 请参看: 上面的 <迭代器模式调用流程图> 唯一的区别就是:
集合实现类 变成了两个,一个是PayManager, 一个是SalaryManager:
代码如下: 使用迭代器模式 给不同具体实现套上不同壳子,壳子里面是每个具体实现的具体写法,但是暴露给客户端的 将是同样的壳子
不使用迭代器模式下 客户端调用写法,次写法无法将工资输出统一起来:
public class Client {
public static void main(String[] args) {
//访问集团的工资列表
PayManager payManager= new PayManager();
//先计算再获取
payManager.calcPay();
Collection payList = payManager.getPayList();
Iterator it = payList.iterator();
System.out.println("集团工资列表:");
while(it.hasNext()){
PayModel pm = (PayModel)it.next();
System.out.println(pm);
}
//访问新收购公司的工资列表
SalaryManager salaryManager = new SalaryManager();
//先计算再获取
salaryManager.calcSalary();
PayModel[] pms = salaryManager.getPays();
System.out.println("新收购的公司工资列表:");
for(int i=0;i<pms.length;i++){
System.out.println(pms[i]);
}
}
}
使用迭代器模式下 客户端写法:
public class Client {
public static void main(String[] args) {
//访问集团的工资列表
PayManager payManager= new PayManager();
//先计算再获取
payManager.calcPay();
System.out.println("集团工资列表:");
test(payManager.createIterator());
//访问新收购公司的工资列表
SalaryManager salaryManager = new SalaryManager();
//先计算再获取
salaryManager.calcSalary();
System.out.println("新收购的公司工资列表:");
test(salaryManager.createIterator());
}
private static void test(Iterator it){
it.first();
while(!it.isDone()){
Object obj = it.currentItem();
System.out.println("the obj=="+obj);
it.next();
}
}
}
迭代器接口:
public interface Iterator {
public void first();
public void next();
public boolean isDone();
public Object currentItem();
}
迭代器实现类之针对数组:
public class ArrayIteratorImpl implements Iterator{
/**
* 用来存放被迭代的聚合对象
*/
private SalaryManager aggregate = null;
private int index = -1;
public ArrayIteratorImpl(SalaryManager aggregate){
this.aggregate = aggregate;
}
public void first(){
index = 0;
}
public void next(){
if(index < this.aggregate.size()){
index = index + 1;
}
}
public boolean isDone(){
if(index == this.aggregate.size()){
return true;
}
return false;
}
public Object currentItem(){
return this.aggregate.get(index);
}
}
迭代器实现类之针对 集合:
public class CollectionIteratorImpl implements Iterator{
/**
* 用来存放被迭代的聚合对象
*/
private PayManager aggregate = null;
private int index = -1;
public CollectionIteratorImpl(PayManager aggregate){
this.aggregate = aggregate;
}
public void first(){
index = 0;
}
public void next(){
if(index < this.aggregate.size()){
index = index + 1;
}
}
public boolean isDone(){
if(index == this.aggregate.size()){
return true;
}
return false;
}
public Object currentItem(){
return this.aggregate.get(index);
}
}
数据集合接口:
public abstract class Aggregate {
/**
* 工厂方法,创建相应迭代器对象的接口
* @return 相应迭代器对象的接口
*/
public abstract Iterator createIterator();
}
数据集合实现类之针对 集合:
public class PayManager extends Aggregate{
/**
* 聚合对象,这里是Java的集合对象
*/
private List list = new ArrayList();
public List getPayList(){
return list;
}
public void calcPay(){
PayModel pm1 = new PayModel();
pm1.setPay(3800);
pm1.setUserName("张三");
PayModel pm2 = new PayModel();
pm2.setPay(5800);
pm2.setUserName("李四");
list.add(pm1);
list.add(pm2);
}
public Iterator createIterator(){
return new CollectionIteratorImpl(this);
}
public Object get(int index){
Object retObj = null;
if(index < this.list.size()){
retObj = this.list.get(index);
}
return retObj;
}
public int size(){
return this.list.size();
}
}
迭代器实现类之针对数组:
public class SalaryManager extends Aggregate{
/**
* 用数组管理
*/
private PayModel[] pms = null;
public PayModel[] getPays(){
return pms;
}
public void calcSalary(){
//计算工资,并把工资信息填充到工资列表里面
//为了测试,做点假数据进去
PayModel pm1 = new PayModel();
pm1.setPay(2200);
pm1.setUserName("王五");
PayModel pm2 = new PayModel();
pm2.setPay(3600);
pm2.setUserName("赵六");
pms = new PayModel[2];
pms[0] = pm1;
pms[1] = pm2;
}
public Iterator createIterator(){
return new ArrayIteratorImpl(this);
}
public Object get(int index){
Object retObj = null;
if(index < pms.length){
retObj = pms[index];
}
return retObj;
}
public int size(){
return this.pms.length;
}
}
PayModel:
public class PayModel {
/**
* 支付工资的人员
*/
private String userName;
/**
* 支付的工资数额
*/
private double pay;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public double getPay() {
return pay;
}
public void setPay(double pay) {
this.pay = pay;
}
public String toString(){
return "userName="+userName+",pay="+pay;
}
}
3 理解迭代器模式:
迭代器的关键思想: 把聚合对象的遍历和访问从聚合对象中分离出来,放入到单独迭代器中,这样迭代器和聚合对象可以独立变化和发展,提高系统灵活性;
使用Java迭代器:使用javase提供的Iterator 取代我们自定义类Iterator, 其余不变
带迭代策略的迭代器:因为迭代和访问数据的分离,因此在迭代中可以增加策略,比如 实现过滤,
对数据进行整条过滤,只能查看自己部门的数据;
对数据进行部分过滤,比如某人不能查看工资数据;
如下即 表示能在迭代器中增加算法 又能增加过滤功能,增加算法后新的数据集合来取代原有数据集合
public ArrayIteratorImpl(SalaryManager aggregate){
//在这里先对聚合对象的数据进行过滤,比如工资必须在3000以下
Collection<PayModel> tempCol = new ArrayList<PayModel>();
for(PayModel pm : aggregate.getPays()){
if(pm.getPay() < 3000){
tempCol.add(pm);
}
}
//然后把符合要求的数据存放到用来迭代的数组
this.pms = new PayModel[tempCol.size()];
int i=0;
for(PayModel pm : tempCol){
this.pms[i] = pm;
i++;
}
}
双向迭代器:同时向前或者向后遍历数据的迭代器 eg:" java.util.ListIterator
优缺点:
4 思考迭代器模式:
本质:控制+访问 ---> 聚合对象中的元素
何时选用:
a) 访问聚合对象的同时不像暴露此对象的内部时
b) 为遍历不同聚合对象提供一个统一接口时
c) 期待以多种方式访问聚合对象时(比如 向后访问, 向前访问, 间隔一个方式访问)
5 迭代器脑图: