设计模式之迭代器模式

一、迭代器模式

迭代器模式可能是JAVA中最广为人知的模式之一,JAVA程序员在使用集合时,并不需要关注其类型是List、Set还是其他的,因为它们的遍历都可以通过迭代器来完成。迭代器模式在客户访问类和聚合类之间插入,分离了聚合对象与其遍历行为,对客户也隐藏了其内部细节,满足单一职责原则和开闭原则。
在这里插入图片描述

  • 抽象聚合(Aggregate): 也叫抽象容器,定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
  • 具体聚合(ConcreteAggregate): 也叫具体容器,实现内部不同结构,返回一个迭代器实例。
  • 抽象迭代器(Iterator): 定义访问和遍历聚合元素的接口。
  • 具体迭代器(ConcreteIterator): 实现抽象迭代器接口中的方法,完成对聚合对象的遍历,记录遍历的当前位置。

二、迭代器模式实现方式

1、抽象迭代器

  我们可以直接使用 JDK 自带的 Iterator 接口,如果不满足自己的需求也可以按照自己的需求自己创建一个。这里我是有的是JDK 自带的 Iterator 接口,我们将源码粘贴过来。

public interface Iterator<E> {
 
    boolean hasNext();
    //使用泛型 E
    E next();
 
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
 
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

2、具体迭代器:

@Data
public class Phone {
    public String name;
    public String money;
}

//List 集合包装为 Iterator 遍历的对象
public class ListIterator implements Iterator<Object>{
    //定义一个 List 集合
    List<Phone> list;
 
    //构造器
    public ListIterator(List<Phone> list) {
        this.list = list;
    }
 
    //获取位数
    int index = 0;
    @Override
    public boolean hasNext() {
        if(list != null && list.size()>index) {
            return true;
        }else {
            return false;
        }
    }
 
    @Override
    public Object next() {
        Phone object = list.get(index);
        index+=1;
        return object;
    }
 
}

//数组集合包装为 Iterator 遍历的对象
public class ArrayIterator implements Iterator<Object>{
    //定义 电话数组
    Phone[] phones;
    //下标
    private int index = 0;
    //构造器
    public ArrayIterator(Phone[] phones) {
        this.phones = phones;
    }
 
    @Override
    public boolean hasNext() {
        if(phones[index] != null && phones.length > index) {
            return true;
        }else {
            return false;
        }
    }
 
    @Override
    public Object next() {
        Phone phone = phones[index];
        index+=1;
        return phone;
    }
 
}

3、 抽象聚合角色

public interface Aggregate {
    //获取手机名称
    public String getName();
    //创建一个获取 Iterator 实例的方法
    public Iterator<Object> createIterator();
    //增加手机的方法
    public void add(String name,String type);
}

4、具体聚合角色

public class XiaoMiPhone implements Aggregate{
    //小米使用 list 存储产品
    private List<Phone> xiaoMis = new ArrayList<Phone>();
    //构造器
    public XiaoMiPhone() {
        add("红米", "1200");
        add("小米6", "2300");
        add("小米7", "3200");
    }
 
    @Override
    public String getName() {
        return "====小米手机====";
    }
    //创建遍历器
    @Override
    public Iterator<Object> createIterator() {
        return new ListIterator(xiaoMis);
    }
        //集合中添加小米产品
    @Override
    public void add(String name, String money) {
        xiaoMis.add(new Phone(name, money));
    }
 
}

public class HuaWeiPhone implements Aggregate{
    //存储华为手机的数据
    Phone phone[];
    private int index = 0;
 
    //构造器
    public HuaWeiPhone() {
        phone = new Phone[5];
        add("荣耀", "1300");
        add("华为P8", "2000");
        add("华为P20", "8000");
    }
 
    @Override
    public String getName() {
        return "====华为手机====";
    }
 
    @Override
    public Iterator<Object> createIterator() {
        return new ArrayIterator(phone);
    }
 
    @Override
    public void add(String name, String money) {
        phone[index] = new Phone(name,money);
        index +=1;
    }
 
}

5、构造一个数据的工厂类(非必须的,我这里是方便测试添加的)

public class Output {
    //定义一个集合
    private List<Aggregate> phones;
 
    //构造器
    public Output(List<Aggregate> phones) {
        this.phones = phones;
    }
 
    //输入方法
    public void outPrit() {
        //先调用 list 自身带的迭代器 Iterator
        Iterator<Aggregate> iterator = phones.iterator();
        // 调用hasNext 方法
        while(iterator.hasNext()) {
            Aggregate aggregate = iterator.next();
            //手机品牌名称
            System.out.println(aggregate.getName());
            //遍历品牌的所有手机,使用我们自己实现的Iterator
            pritlnPhone(aggregate.createIterator());
        }
    }
 
 
    private void pritlnPhone(Iterator<Object> createIterator) {
        while(createIterator.hasNext()) {
            Phone phone = (Phone) createIterator.next();
            System.out.println("品牌="+phone.getName()+"-----金额="+phone.getMoney());
        }
    }
 
}

6、测试

public class Client {
 
    public static void main(String[] args) {
        //手机店集合
        List<Aggregate> phones = new ArrayList<>();
        //创建华为手机 == 数组
        HuaWeiPhone huaWeis = new HuaWeiPhone();
        //创建小米手机 == list
        XiaoMiPhone xiaoMis = new XiaoMiPhone();
 
        //将其都加入到手机店集合
        phones.add(huaWeis);
        phones.add(xiaoMis);
 
        //调用公共的输入类
        Output output = new Output(phones);
        output.outPrit();
        /**
         * 结构如下:
         * ====华为手机====
        品牌=荣耀-----金额=1300
        品牌=华为P8-----金额=2000
        品牌=华为P20-----金额=8000
        ====小米手机====
        品牌=红米-----金额=1200
        品牌=小米6-----金额=2300
        品牌=小米7-----金额=3200
         */
    }
 
}

三、迭代器模式应用源码分析

分析一下 arrayList 的 iterator 的使用

1、先了解下 ArrayList 的 Iterator 的使用:

public class IteratorDemo {
 
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("t");// ..
        // 获取到迭代器
        Iterator<String> Itr = list.iterator();
        while (Itr.hasNext()) {
            System.out.println(Itr.next());
        }
    }
 
}

2、进入 ArrayList(相当于具体聚合对象)的源码:实现了 List 接口,实现了 Iterator 方法,返回遍历对象:Iterator。

public class ArrayList<E> extends AbstractList<E>
        implements List<E>
{
    ...
        public Iterator<E> iterator() {
        return new Itr();
    }
    ...
}

3、进入 List(相当于抽象聚合对象) 接口查看:发现包含一个 Iterator 的抽象方法 。

public interface List<E> extends Collection<E> {
    ...
    Iterator<E> iterator();
    ...
}

4、我们进入返回的 Iterator 对象的类 Itr (相当于具体的迭代器),是 ArraList 类的内部类。查看 hasNext()方法,会发现遍历的对象是 Object[] 数组,具体的迭代器类(实现 hasNext 和 Next 方法)

private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;
 
        public boolean hasNext() {
            return cursor != size;
        }
 
        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
 
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();
 
            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
 
        ......
    }

5、上述具体迭代器角色实现了 Iterator 接口,也就是抽象迭代器角色。与我们的案例中实现同一个接口,就不展示了。

四、迭代器模式总结

优点

  • 访问一个聚合对象的内容而无须暴露它的内部表示。
  • 遍历任务交由迭代器完成,这简化了聚合类。
  • 它支持以不同方式遍历一个聚合,甚至可以自定义迭代器的子类以支持新的遍历。
  • 增加新的聚合类和迭代器类都很方便,无须修改原有代码。
  • 封装性良好,为遍历不同的聚合结构提供一个统一的接口

缺点:

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

应用场景

  • 访问一个聚合对象的内容而无须暴露它的内部表示。
  • 需要为聚合对象提供多种遍历方式。
  • 为遍历不同的聚合结构提供一个统一的接口。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值