鸣谢:《大话设计模式》

简介

是一种行为型设计模式,
它提供了一种访问集合对象元素的方法,而无需暴露集合的内部表示。迭代器模式将集合与迭代逻辑分离,使得客户端能够独立地遍历集合中的元素,而不必关心集合的具体实现细节。

需要对聚集有多种方式遍历时,可以考虑用迭代器模式

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

java Iterator

Java.util.Iterator支持对集合的简单迭代接口。

public interface Iterator<E> {
    boolean hasNext();
    E next();
}

Java.util.ListIterator支持对集合的任意方向上迭代接口。

public interface ListIterator<E> extends Iterator<E> {
    boolean hasNext();

    E next();

    boolean hasPrevious();

    E previous();
}

这两个接口要比我们下面写的抽象类Iterator更简洁,功能更强,其实是对GOF设计改良的结果。

主要组成部分:

  • 迭代器(Iterator):迭代器是抽象接口,它定义了用于遍历集合的方法,如next()(获取下一个元素)、hasNext()(检查是否有下一个元素)等。

  • 具体迭代器(Concrete Iterator):具体迭代器是迭代器接口的实现,它负责管理遍历集合的状态,并实现具体的遍历逻辑。

  • 聚合(Aggregate):聚合是包含元素的集合,它通常提供一个工厂方法用于创建迭代器对象,以便客户端可以获得迭代器并遍历集合。

  • 具体聚合(Concrete Aggregate):具体聚合是聚合接口的实现,它创建并返回一个具体的迭代器对象,使客户端能够遍历集合。

工作流程

  • 客户端获取聚合对象的迭代器,开始遍历集合。

  • 迭代器负责跟踪当前遍历位置,提供方法来访问集合中的元素。

  • 客户端使用迭代器提供的方法来遍历集合,直到遍历完成。

  • 客户端无需关心集合的内部结构,只需关心迭代器接口提供的方法,从而实现了集合的封装。


例子

结构

代码

迭代器(Iterator)

/**
 * @author: lpy
 * @Date: 2023/10/30
 */
public interface Iterator {
    Object first();
    Object next();
    boolean isDone();
    Object currentItem();
}

具体迭代器(Concrete Iterator)

/**
 * @author: lpy
 * @Date: 2023/10/30
 */
public class ConcreteIterator implements Iterator {
    private ConcreteAggregate aggregate;
    private int current = 0;

    public ConcreteIterator(ConcreteAggregate aggregate){
        this.aggregate = aggregate;
    }

    @Override
    public Object first() {
        return aggregate.geCurrentItem(0);
    }

    @Override
    public Object next() {
        Object ret = null;
        current++;
        if (current>aggregate.getCount()){
            return ret;
        }
        ret = aggregate.geCurrentItem(current);
        return ret;
    }

    @Override
    public boolean isDone() {
        return current >=aggregate.getCount();
    }

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

聚合(Aggregate)

/**
 * @author: lpy
 * @Date: 2023/10/30
 */
public abstract class Aggregate {
    public abstract Iterator createIterator();
}

具体聚合(Concrete Aggregate)

 * @author: lpy
 * @Date: 2023/10/30
 */
public class ConcreteAggregate extends Aggregate{
    private ArrayList<Object> items = new ArrayList<>();
    @Override
    public Iterator createIterator() {
        return null;
    }

    public Object geCurrentItem(int index){
        return items.get(index);
    }
    public Object add(Object o){
        return items.add(o);
    }
    public int getCount(){
        return items.size();
    }
}

测试类

/**
 * @author: lpy
 * @Date: 2023/10/30
 */
public class IteratorTest {
    public static void main(String[] args) {
        ConcreteAggregate ca = new ConcreteAggregate();
        ca.add("1");
        ca.add("2");
        ca.add("3");
        ca.add("4");
        ca.add("5");
        ca.add("6");
        ConcreteIterator iterator = new ConcreteIterator(ca);
        System.out.println(iterator.isDone());
        System.out.println(iterator.next());
        System.out.println(iterator.next());
        System.out.println(iterator.isDone());
        System.out.println(iterator.next());
        System.out.println(iterator.next());
        System.out.println(iterator.next());
        System.out.println(iterator.isDone());
    }
}

应用

java 底层语言就实现了,用的很多,但自己实现不多。

迭代器模式优缺点

  • 优点:
    • 简化客户端代码:迭代器模式允许客户端通过统一的接口遍历不同类型的集合,简化了客户端代码。

    • 解耦合:迭代器模式将遍历逻辑与集合的实现分离,使集合可以独立演化,不影响遍历方式。

    • 支持多种遍历方式:通过不同的迭代器实现,可以支持不同的遍历方式,如正向遍历、逆向遍历、按条件遍历等。

    • 隐藏集合细节:客户端无需关心集合的内部结构,只需使用迭代器接口即可访问元素。

  • 缺点:

    • 复杂性增加:引入迭代器模式会增加代码的复杂性,因为需要创建迭代器接口和具体迭代器类,以及在聚合类中实现创建迭代器的方法。

    • 性能开销:在某些情况下,使用迭代器可能会引入性能开销。例如,如果需要频繁遍历大型集合,迭代器的操作可能会导致性能下降。

    • 不适用于所有情况:迭代器模式并不总是适用于所有类型的集合。有些集合可能没有内部迭代器的需求,或者可以使用其他方式更有效地进行遍历。

    • 迭代器的状态管理:具体迭代器类需要维护迭代过程中的状态,这可能会增加复杂性和潜在的错误。

    • 不支持并发访问:传统的迭代器模式通常不支持并发访问。如果多个线程需要同时访问集合,可能需要额外的同步措施。

7 大设计原则

不能全部遵守 , 也不能不遵守 , 注意平衡 功能 和 系统复杂度 , 找到最合适的一个点 ;

- 单一职责原则(Single Responsibility Principle - SRP):
这个原则规定一个类应该只有一个改变的理由,也就是说,一个类应该只有一个单一的职责。这有助于保持类的简单性和可维护性,因为每个类只需关注一个特定的功能。

- 开放-封闭原则(Open-Closed Principle - OCP):
开放-封闭原则要求系统中的软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。这意味着当需要添加新功能时,应该通过扩展现有代码来实现,而不是修改原有代码。

- 里氏替换原则(Liskov Substitution Principle - LSP):
里氏替换原则规定,子类应该能够替换其父类,而不会影响程序的正确性。也就是说,子类应该继承父类的行为,但可以扩展或修改该行为,但不应该改变父类的行为。

- 接口隔离原则(Interface Segregation Principle - ISP):
接口隔离原则要求一个类不应该强迫其客户端依赖于它们不需要的接口。应该根据客户端的需求定义小而精确的接口,而不是大而笨重的接口。

- 依赖倒置原则(Dependency Inversion Principle - DIP):
依赖倒置原则要求高级模块不应该依赖于低级模块,它们都应该依赖于抽象。具体来说,这意味着应该通过抽象接口或抽象类来定义模块之间的依赖关系,而不是直接依赖于具体实现。

- 迪米特法则(Law of Demeter - LoD):
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

- 合成复用原则(Composite Reuse Principle - CRP):
合成复用原则鼓励通过组合(合成)已有的类来实现新功能,而不是通过继承现有的类。这样可以降低系统的耦合度,并且更加灵活。

源码位置

全部源码github.com/xs-alpha/designPattern

参考文献

如有内容侵权,麻烦联系博主删除

浙公网安备33011302000604

辽ICP备20003309号