设计模式——迭代器模式


作者:云都小生


推荐学习资源



史上最全的设计模式导学目录

十分推荐!


概述



迭代器模式是比较容易理解,且使用频率非常高的一种设计模式,它的本质是 实现了数据聚合对象的存储与遍历的解耦,使数据聚合不会暴露在数据操作方法面前。

在现实的开发中,我们经常会碰到一种情况,我们需要存储许多的对象,有时候需要对这些对象进行遍历。

一般去设计的时候,都是把存储和遍历两种功能放到同一个类中,但是这样会产生许多的问题。

首先,违背了“单一职责”,每个类/方法都应该只负责一件事,聚合类既负责存储又负责遍历。

其次,违背了“封装性”,你想想看,如果存储数据和操作数据的方法放在同一个类,那么存储的数据就会都暴露出来。


设计中的角色



通常许多编程语言的标准库,都为我们实现了迭代器,但是为了了解迭代器的具体细节,所以我也学着去实现一下。先了解一下整个设计的框架。

抽象聚合类:该抽象类封装了一般聚合类都需要的属性和方法,它需要存储很多元素对象,所以需要内置List。它需要创建自己对应的一个迭代器,所以需要一个方法createIterator()。

具体聚合类:继承了抽象聚合类,实现了抽象聚合类的抽象方法,具体聚合类可以生成自己相对应的迭代器。

抽象迭代器:声明了迭代器对聚合数据的遍历方法,
定义了共同的属性。

具体迭代器:继承了抽象迭代器类,实现了具体的遍历方法。


案例1——独自实现迭代器


通过查看一些参考手册,我们知道迭代器和聚合对象通常需要一些什么属性和方法,利用抽象类封装起来。

import java.util.*;

//抽象聚合类
public abstract class AbstractAggregated {
    //该聚合数据只有子类能看到,良好的封装
    protected List<Object> objects = new ArrayList<Object>();


    public AbstractAggregated(List objects)
    {
        this.objects = objects;
    }

    //增加元素
    public void addObject(Object obj) {  
        this.objects.add(obj);  
    }  

    //删除元素
    public void removeObject(Object obj) {  
        this.objects.remove(obj);  
    }  

    //返回List
    public List getObjects() {  
        return this.objects;  
    }  

    //声明创建迭代器对象的抽象工厂方法  
    public abstract AbstractIterator createIterator(); 
}

import java.util.List;

//具体聚合类
public class TestAggregated extends AbstractAggregated {
    public TestAggregated(List objects) {  
        super(objects);  
    }  

    //实现创建迭代器对象的具体工厂方法  
    public AbstractIterator createIterator() {  
        return new TestIterator(this);  
    }  
}


public abstract class AbstractIterator {
    public abstract void next(); //移至下一个元素  
    public abstract boolean isLast(); //判断是否为最后一个元素  
    public abstract void previous(); //移至上一个元素  
    public abstract boolean isFirst(); //判断是否为第一个元素  
    public abstract Object getNextItem(); //获取下一个元素  
    public abstract Object getPreviousItem(); //获取上一个元素  
}

import java.util.*;

public class TestIterator extends AbstractIterator {
    private TestAggregated testAggregated;
    private List objects;
    private int cursor1;
    private int cursor2;

    public TestIterator(TestAggregated testAggregated) {
        this.testAggregated = testAggregated;
        this.objects = testAggregated.objects;
        if(objects.isEmpty())
        {
            cursor1 = -1;
            cursor2 = -1;
        }
        else
        {
            cursor1 = 0;
            cursor2 = objects.size()-1;
        }
    }

    //把正序游标调整到下一个元素
    public void next() {
        if(cursor1 < objects.size())
        {
            cursor1++;
        }
    }

    //判断是否是最后一个元素
    public boolean isLast() {
        return (cursor1 == objects.size());
    }

    //把逆序的游标调整到上一个元素
    public void previous() {
        if(cursor2 > -1)
        {
            cursor2--;
        }
    }

    //判断是否是第一个元素
    public boolean isFirst() {
        return (cursor2 == -1);
    }

    //获取下一个元素
    public Object getNextItem() {
        return objects.get(cursor1);  
    }

    //获取上一个元素
    public Object getPreviousItem() {
        return objects.get(cursor2);
    }
}

//客户端测试类
public class Client {
    public static void main(String[] args) {
        List objects = new ArrayList();
        objects.add("A");
        objects.add("B");
        objects.add("C");
        objects.add("D");

        AbstractAggregated list = new TestAggregated(objects);
        AbstractIterator iterator = list.createIterator();

         System.out.println("正向遍历:");      
         while(!iterator.isLast())
         {  
             System.out.print(iterator.getNextItem() + ",");  
             iterator.next();  
         }  
         System.out.println();  
         System.out.println("-----------------------------");  
         System.out.println("逆向遍历:");  
         while(!iterator.isFirst()) 
         {  
             System.out.print(iterator.getPreviousItem() + ",");  
             iterator.previous();  
         }  
    }
}


案例2——利用IDK内置的迭代器


我们可以直接用标准库里面的Collection和Iterator,来进行遍历。

import java.util.*;

public class Client {
    public static void main(String[] args) {
        Collection objects = new ArrayList();

        objects.add("A");
        objects.add("B");
        objects.add("C");
        objects.add("D");

        traverse(objects);
    }

    public static void traverse(Collection c)
    {
        Iterator i = c.iterator();

        while(i.hasNext())
        {
            System.out.println(i.next().toString());
        }
    }
}


总结



迭代器模式本质上是聚合类与迭代类之间的解耦,简化了聚合类,引入了迭代器。并且,我们还可以在掘和对象自定义多种遍历方法,符合开闭原则,可以增加新的遍历方式。

2018/1/16 16:21:48 @Author:云都小生

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值