大话设计模式读书笔记(迭代器模式)

人物:大鸟,小菜

事件:大鸟小菜去乘公交车,上车后看见售票员要求乘客进行买票,并发现售票员不管是谁,只要有对方一上车,就能准确记住并叫住他让他买票,而且不管对方什么身份,不管你是公司员工还是小偷,只要上车,就要买票,大鸟由此给小菜讲解了迭代器模式。


迭代器模式:

1.对迭代器进行简介

2.通过迭代器实现公交车买票事件

3.反向遍历,通过迭代器实现公交车买票事件

迭代器模式简介

1.概念:提供一种方法,顺序访问一个聚合对象中各个元素,而又不暴露对象的内部表示。

2.用到的场景:

  (1)售票员不管是小偷还是公司员工,不管是中国人还是外国人,只要上车都要买票,也就是说当需要访问一个聚合对象,而且不管这些对象是什么都需要遍历的时候,就应该考虑迭代器模式

  (2)售票员可以从车头到车尾来售票,也可以从车尾到车头来售票,当需要对聚合对象进行多种方式遍历时,可以考虑用迭代器模式

3.举例:迭代器模式是为了遍历不同的聚合对象,提供如开始,下一个,是否结束,当前哪一项等统一的接口,如很常见的for(;;)

迭代器实现

1.结构图:

2.代码实现:

Iterator类,迭代器抽象类:

public abstract class Iterator {
    public abstract Object first();

    public abstract Object next();

    public abstract boolean isDone();

    public abstract Object currentItem();
}

Aggregate类,聚合抽象类:

//用于创建迭代器
public
abstract class Aggregate { public abstract Iterator createIterator(); }

ConcreteIterator类,具体迭代器类:

@Data
public class ConcreteIterator extends Iterator {
    private ConcreteAggregate aggregate;
    private int current = 0;

//初始化时,将具体的聚合对象传入
public ConcreteIterator(ConcreteAggregate aggregate) { this.aggregate = aggregate; }
//得到聚合的第一个对象 @Override
public Object first() { return aggregate.getItems().get(0); }
//得到聚合的下一个对象 @Override
public Object next() { Object ret = null; current++; if (current < aggregate.count()) { ret = aggregate.getItems().get(current); } return ret; } @Override public boolean isDone() { return current >= aggregate.count() ? true : false; }
//返回当前的聚合对象 @Override
public Object currentItem() { return aggregate.getItems().get(current); } }

ConcreteAggregate类,具体聚合类,继承Aggregate

public class ConcreteAggregate extends Aggregate {
    private List<Object> items = new ArrayList<>();

    @Override
    public Iterator createIterator() {
        return new ConcreteIterator(this);
    }

    public int count() {
        return items.size();
    }

    public List<Object> getItems() {
        return items;
    }

    public void setItems(List<Object> items) {
        this.items = items;
    }
}

客户端代码:

@Slf4j
public class IteratorClient {
    public static void main(String[] args) {
        ConcreteAggregate a = new ConcreteAggregate();
        List<Object> items = new ArrayList<>();
        Object a0 = "大鸟";
        Object a1 = "小菜";
        Object a2 = "行李";
        Object a3 = "老外";

        items.add(a0);
        items.add(a1);
        items.add(a2);
        items.add(a3);
        a.setItems(items);

        Iterator iterator = new ConcreteIterator(a);
        Object item = iterator.first();
        while (!iterator.isDone()) {
            log.info(iterator.currentItem() + "请买车票");
            iterator.next();
        }
    }
}

输出结果:

大鸟请买车票
小菜请买车票
行李请买车票
老外请买车票

小菜:为什么非要用Iterator抽象类呢,好像直接使用也是可以的

大鸟:那是因为你没有注意到迭代器的第二个好处 --> 当你需要对聚合对象进行多种方式遍历时,可以考虑用迭代器模式 

小菜从后向前遍历版的迭代器实现

ConcreteIteratorDesc类,实现一个从后向前的迭代器:

public class ConcreteIteratorDesc extends Iterator {
    private ConcreteAggregate aggregate;
    private int current = 0;

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

    @Override
    public Object first() {
        return aggregate.getItems().get(aggregate.count() - 1);
    }

    @Override
    public Object next() {
        Object ret = null;
        current--;
        if (current >= 0) {
            ret = aggregate.getItems().get(current);
        }
        return ret;
    }

    @Override
    public boolean isDone() {
        return current < 0 ? true : false;
    }

    @Override
    public Object currentItem() {
        return aggregate.getItems().get(current);
    }
}

客户端:

//Iterator iterator = new ConcreteIterator(a);
Iterator iterator = new ConcreteIteratorDesc(a);

输出结果如下,与之前结果相反:

老外请买车票
行李请买车票
小菜请买车票
大鸟请买车票

总体来说:迭代模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码透明地访问集合内部的数据。

原文地址:https://www.cnblogs.com/wencheng9012/p/13442047.html