zoukankan      html  css  js  c++  java
  • 迭代器模式

    2021年11月27日18:24:29

    迭代器模式

    定义

    Provide a way to access the elements of an aggregate object sequentially without
    exposing its underlying representation. ——《Design Patterns: Elements of Reusable Object-Oriented Software》
    

    提供一种顺序访问集合的元素而不暴露其底层表示的方法。 ——《设计模式:可复用面向对象软件的基础》

    迭代器模式是一种行为型模式。

    明明讲

    迭代器模式就是提供一种遍历的方法,这种方法有两个特点:一是按你想要的方式访问到你想访问的元素,二是不暴露底层是什么存的,怎么存的。

    在开发过程中,我们使用类库提供给我们的集合,遍历集合中的元素,使用的就是迭代器。一般情况下,单单作为使用者,我们是不会去关注这些集合底层结构是什么,只需要拿到我们需要的数据,进行业务逻辑的处理就可以了。但是呢,作为一个优秀的开发者,当然要深入了解各种集合的数据结构及操作的。当然啦,我们是不会说我们是为了面试才去了解的啦。(此处应该有表情)

    常见用法:

        List<String> list = new ArrayList<>();
        list.add("ming");
        list.add("ming");
        list.add("come");
        for(String s : list) {
            System.out.println(s);
        }
    

    上面代码中的for循环遍历列表中的数据,Java编译器会将这段代码变成使用ArrayList中的迭代器去遍历数据。编译之后再反编译,代码如下:

        List<String> list = new ArrayList();
        list.add("ming");
        list.add("ming");
        list.add("come");
        Iterator var1 = list.iterator();
    
        while(var1.hasNext()) {
            String s = (String)var1.next();
            System.out.println(s);
        }
    

    图示

    迭代器模式结构图:

    迭代器模式结构图

    角色

    抽象迭代器角色(Iterator):

    • 定义一个接口,用于访问和遍历元素,它的方法一般有:first、next、hasNext等。

    具体迭代器角色(ConcreteIterator):

    • 实现【抽象迭代器角色】定义的执行操作
    • 记录集合迭代时的当前位置,如图中的currentItem()方法
    • 当客户端控制迭代,迭代器被称作外部迭代器;当迭代器控制迭代,迭代器是内部迭代器。(When the client controls the iteration, the iterator is called an external
      iterator, and when the iterator controls it, the iterator is aninternal iterator.)
    • Java类库中AbstractList、ArrayList、HashMap中都有具体迭代器

    抽象集合角色(Aggregate):

    • 定义了一个接口,用于创建迭代器对象

    具体集合角色(ConcreteAggregate):

    • 实现【抽象集合角色】,实现创建迭代器对象方法,返回一个迭代器实例

    代码示例

    家有小女,名为晓月,一岁有余,嘤嘤学语。

    除夕佳节,给家人拜年,爷爷奶奶,爸爸妈妈,叔叔婶婶,还有晓月自己,新年快乐。

    类图:

    代码示例类图

    抽象迭代器角色:
    public interface NameIterator {
        String next();
        boolean hastNext();
    }
    
    抽象集合角色:
    public interface FamilyAggregate {
        NameIterator createIterator();
        boolean addFamily(int generation, String name);
    }
    
    
    具体集合角色和具体迭代器角色:
    // 具体集合类
    public class FamilyAggregateImpl implements FamilyAggregate {
    
        private int generation;
    
        private List<String>[] generations;
    
        public FamilyAggregateImpl(int generation) {
            this.generation = generation;
            this.generations = initFamily(generation);
        }
    
        private List<String>[] initFamily(int generation) {
            List<String>[] name = new ArrayList[generation];
            for (int i = 0; i < generation; i++) {
                name[i] = new ArrayList<>();
            }
            return name;
        }
    
        public boolean addFamily(int generation, String name) {
            return generations[generation - 1].add(name);
        }
    
        @Override
        public NameIterator createIterator() {
            return new NameIteratorImpl();
        }
    
        // 具体迭代器
        private class NameIteratorImpl implements NameIterator {
    
            int currentGeneration;
    
            int cursor;
    
            NameIteratorImpl() {
                this.currentGeneration = FamilyAggregateImpl.this.generation;
            }
    
            @Override
            public String next() {
                int i = cursor;
                List<String>[] generations = FamilyAggregateImpl.this.generations;
                if (currentGeneration == 1 && cursor == generations.length) {
                    System.out.println("无剩余可遍历");
                }
                String name = generations[currentGeneration - 1].get(i);
                cursor = i + 1;
                if (cursor == generations[currentGeneration - 1].size()) {
                    currentGeneration--;
                    cursor = 0;
                }
                return name;
            }
    
            @Override
            public boolean hastNext() {
                return currentGeneration != 0;
            }
        }
    
    }
    
    客户端
    public class Client {
        public static void main(String[] args) {
            FamilyAggregate family = new FamilyAggregateImpl(3);
    
            family.addFamily(1, "晓月");
            family.addFamily(2, "爸爸");
            family.addFamily(2, "妈妈");
            family.addFamily(2, "叔叔");
            family.addFamily(2, "婶婶");
            family.addFamily(3, "爷爷");
            family.addFamily(3, "奶奶 ");
    
            NameIterator iterator = family.createIterator();
            while (iterator.hastNext()) {
                String name = iterator.next();
                System.out.println(name);
            }
    
        }
    }
    

    结果如下:

    爷爷
    奶奶 
    爸爸
    妈妈
    叔叔
    婶婶
    晓月
    

    使用场景

    • 1、访问一个聚合对象的内容而无须暴露它的内部表示。
    • 2、可以为聚合对象提供多种遍历方式,比如顺序、逆序等。
    • 3、为遍历不同的聚合结构提供一个统一的接口,比如访问下一个元素的方法是next。

    优点

    • 1、它支持以不同的方式遍历一个聚合对象。
    • 2、迭代器简化了聚合类。
    • 3、在同一个聚合上可以有多个遍历。
    • 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。

    缺点

    • 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

    总结

    迭代器模式应该是最常见的设计模式了,可以说Java程序员只要开发,都要使用它。

    迭代器模式是一种行为型设计模式,它为集合提供了一个遍历元素的方式,又不会暴露它的内部表示。

    2021年12月7日01:47:38

    由于博主水平有限,如果本文有什么错漏,请不吝赐教

    感谢阅读,如果您觉得本文对你有帮助的话,可以点个推荐

  • 相关阅读:
    4-9 内置函数和匿名函数的题
    4-09 试题
    4--2日 函数 装饰器 作业题
    if 语句
    4-4日 内置函数,匿名函数
    4-4日 列表推导式,生成器推导式
    4-3日 迭代器 生成器
    4-2日装饰器,带参数的装饰器
    python 函数名 、闭包 装饰器 day13
    [LeetCode]-DataBase-Department Top Three Salaries
  • 原文地址:https://www.cnblogs.com/mingmingcome/p/15652788.html
Copyright © 2011-2022 走看看