想走?可以!先买票--迭代器模式

1.1 乘车买票,不管你是谁!

售票员检查谁没有买票,把车厢里的人都遍历一遍。

1.2 迭代器模式

        迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。[DP]
        "你想呀,售票员才不管你上来的是人还是物(行李),不管是中国人还是外国人,不管是不是内部员工,甚至哪怕是马上要抓走的小偷,只要是来乘车的乘客,就必须要买票。同样道理,当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,你就应该考虑用迭代器模式。另外,售票员从车头到车尾来售票,也可以从车尾向车头来售票,也就是说,你需要对聚集有多种方式遍历时,可以考虑用迭代器模式。由于不管乘客是什么,售票员的做法始终是相同的,都是从第一个开始,下一个是谁,是否结束,当前售到哪个人了,这些方法每天他都在做,也就是说,为遍历不同的聚集结构提供如开始、下一个、是否结束、当前哪一项等统一的接口。"

        "哈,本来这个模式还是有点意思的,不过现今来看迭代器模式实用价值远不如学习价值大了,Martin Flower甚至在自己的网站上提出撤销此模式。因为现在高级编程语言如C#、Java等本身已经把这个模式做在语言中了。"
        "哦,是什么?"
        "哈,foreach你熟悉吗?"
        "啊,原来是它,没错没错,它就是不需要知道集合对象是什么,就可以遍历所有的对象的循环工具,非常好用。"
        "另外还有像Iterator接口也是为迭代器模式而准备的。不管如何,学习一下GoF的迭代器模式的基本结构,还是很有学习价值的。研究历史是为了更好地迎接未来。"

1.3 迭代器实现

迭代器模式(Iterator)结构图

package code.chapter20.iterator1;

import java.util.ArrayList;

public class Test {
	
	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

        ConcreteAggregate bus = new ConcreteAggregate();
        bus.add("大鸟");
        bus.add("小菜");
        bus.add("行李");
        bus.add("老外");
        bus.add("公交内部员工");
        bus.add("小偷");

        //正序迭代器
        //Iterator conductor = new ConcreteIterator(bus);
        //倒序迭代器
        Iterator conductor = new ConcreteIteratorDesc(bus);

        conductor.first();
        while (!conductor.isDone()) {
            System.out.println(conductor.currentItem() + ",请买车票!");
            conductor.next();
        }

		System.out.println();
		System.out.println("**********************************************");

	}
}

//聚集抽象类
abstract class Aggregate{
    //创建迭代器
    public abstract Iterator createIterator();
}

//具体聚集类,继承Aggregate
class ConcreteAggregate extends Aggregate{

    //声明一个ArrayList泛型变量,用于存放聚合对象
    private ArrayList<Object> items = new ArrayList<Object>();
    public Iterator createIterator(){
        return new ConcreteIterator(this);
    }

    //返回聚集总个数
    public int getCount(){
        return items.size();
    }

    //增加新对象
    public void add(Object object){
        items.add(object);
    }
    
    //得到指定索引对象
    public Object getCurrentItem(int index){
        return items.get(index);
    }

}

//迭代器抽象类
abstract class Iterator{

    public abstract Object first();         //第一个
    public abstract Object next();          //下一个
    public abstract boolean isDone();       //是否到最后
    public abstract Object currentItem();   //当前对象

}

//具体迭代器类,继承Iterator
class ConcreteIterator extends Iterator{
    private ConcreteAggregate aggregate;
    private int current = 0;

    //初始化时将具体的聚集对象传入
    public ConcreteIterator(ConcreteAggregate aggregate){
        this.aggregate = aggregate;
    }

    //得到第一个对象
    public Object first(){
        return aggregate.getCurrentItem(0);
    }

    //得到下一个对象
    public Object next() {
        Object ret = null;
        current++;
        if (current < aggregate.getCount()) {
            ret = aggregate.getCurrentItem(current);
        }
        return ret;
    }

    //判断当前是否遍历到结尾,到结尾返回true
    public boolean isDone(){
        return current >= aggregate.getCount() ? true : false;
    }

    //返回当前的聚集对象
    public Object currentItem(){
        return aggregate.getCurrentItem(current);
    }
}

//具体迭代器类(倒序),继承Iterator
class ConcreteIteratorDesc extends Iterator{
    private ConcreteAggregate aggregate;
    private int current = 0;

    public ConcreteIteratorDesc(ConcreteAggregate aggregate){
        this.aggregate = aggregate;
        current = aggregate.getCount()-1;
    }

    //第一个对象
    public Object first(){
        return aggregate.getCurrentItem(aggregate.getCount()-1);
    }

    //下一个对象
    public Object next() {
        Object ret = null;
        current--;
        if (current >= 0) {
            ret = aggregate.getCurrentItem(current);
        }
        return ret;
    }

    //判断当前是否遍历到结尾,到结尾返回true
    public boolean isDone(){
        return current <0 ? true : false;
    }

    //返回当前的聚集对象
    public Object currentItem(){
        return aggregate.getCurrentItem(current);
    }
}



Aggregate聚集抽象类:
ConcreteAggregate具体聚集类:继承Aggregate。
Iterator迭代器抽象类:
ConcreteIterator具体迭代器类:继承Iterator。

        其实售票员完全可以用更多的方式来遍历乘客,比如从最高的到最矮的、从最小到最老、从最靓丽酷毙到最猥琐龌龊。

1.4 Java的迭代器师兄

        "刚才我们也说过,实际使用当中是不需要这么麻烦的,因为Java语言中已经为你准备好了相关接口,你只需去实现就好。"
        Java.util.Iterator支持对集合的简单迭代接口。
        Java.util.ListIterator支持对集合的任意方向上迭代接口。
        "你会发现,这两个接口要比我们刚才写的抽象类Iterator简洁,但可实现的功能却一点不少,这其实也是对GoF的设计改良的结果。"
        "其实具体类实现这两个接口的代码也差别不大,是吗?"
        "是的,区别不大,另外这两个是可以实现泛型的接口,去查Java的API帮助就可以了。"
        "有了这个基础,你再来看你最熟悉的foreach就很简单了。"
        "这里用到了foreach而在编译器里做了些什么呢?其实它做的是下面的工作。"
        "原来foreach就是实现Iterator来实际循环遍历呀。"
        "如果我们想实现刚才的反向遍历。那就用另一个接口实现。"

package code.chapter20.iterator2;

import java.util.Iterator;
import java.util.ListIterator;
import java.util.ArrayList;

public class Test {
	
	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

        ArrayList<String> bus = new ArrayList<String>();
        bus.add("大鸟");
        bus.add("小菜");
        bus.add("行李");
        bus.add("老外");
        bus.add("公交内部员工");
        bus.add("小偷");
        
        System.out.println("foreach遍历:");
        for(String item : bus){

            System.out.println(item + ",请买车票!");

        }
        
        System.out.println();
    
        System.out.println("Iterator遍历:");
        Iterator<String> conductor = bus.iterator();
        while (conductor.hasNext()) {
            System.out.println(conductor.next() + ",请买车票!");
        }
        
        System.out.println();
        
        System.out.println("ListIterator逆向遍历:");
        ListIterator<String> conductorDesc = bus.listIterator(bus.size());

        while (conductorDesc.hasPrevious()) {
        
            System.out.println(conductorDesc.previous() + ",请买车票!");
        
        }

		System.out.println();
		System.out.println("**********************************************");

	}
}

public interface Iterator{

    public boolean hasNext();       //如果迭代具有更多元素,则返回true 
    public Object next();           //返回迭代中的下一个元素
    
}

public interface ListIterator{

    public boolean hasNext();       //如果此列表迭代器在向前遍历列表时具有更多元素,则返回true 
    public Object next();           //返回列表中的下一个元素并前进光标位置

    public boolean hasPrevious();   //如果此列表迭代器在反向遍历列表时具有更多元素,则返回true
    public Object previous();       //返回列表中的上一个元素并向后移动光标位置
    
}



        "是的,尽管我们不需要显式地引用迭代器,但系统本身还是通过迭代器来实现遍历的。总的来说,迭代器(Iterator)模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码透明地访问集合内部的数据。迭代器模式在访问数组、集合、列表等数据时,尤其是数据库数据操作时,是非常广泛的应用,但由于它太普遍了,所以各种高级语言都对它进行了封装,所以反而给人感觉此模式本身不太常用了。"

1.5 迭代高手

        "哈哈,看来那个售票员是最了不起的迭代高手,每次有乘客上车他都数数,统计人数,然后再对整车的乘客进行迭代遍历,不放过任何漏网之鱼,啊,应该是逃票之人。"
        "隔行如隔山,任何行业都有技巧和经验,需要多思考、多琢磨,才能做到最好的。"
        "嗯,编程又何尝不是这样,我相信代码没有最好,只有更好,我要继续努力。"

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值