设计模式(12)迭代器模式(讲解+应用)

目录

  1. 迭代器模式

  2. 为什么要用迭代器模式

  3. 迭代器模式应用实例

迭代器模式

不知不觉更了12篇,从今天开始近乎每天全满的课程开始了,更新速度也要受到影响。

迭代器,最早听到这个概念的时候是在大一的时候还对java一知半解就去搞Android的时候,接触到的,在用到对于数据库的操作的时候,我们来获得数据的时候通过 rawQuery执行sql语句来获得数据集返回的就是一个游标实例,Cursor,因此迭代器模式也被称作是游标模式,具体例子和其使用在后面实例部分介绍。

迭代器:提供一种方法来遍历集合的同时,又不暴露该集合的底层数据存储的实现。

为什么要使用迭代器模式

我们常见的集合有很多种类,其顶层数据存储和组织方式的不同导致了我们在对数据进行遍历的时候存在一些差异,迭代器模式就是通过实现某种统一的方式来实现对不同的集合的遍历,同时又不暴露出其底层的数据存储和组织方式。

继续我们造机器的问题,在讲适配器的时候提到了,我们拥有不止一个商店,而且每个商店里所出售的货物的种类也是不同的,惧于马云大大的“不做电子商务将无商可务”,决定不仅仅是通过线下的这种销售,在网上也进行出售,网上的店将作为一个集合,集合线下店里所有的产品,当有客户下单,就有具有该上商品的网店进行发货,那么第一个要解决的问题就是我要知道这些商店里都有什么产品,所以需要他们给提供一个货物的种类单,由于不同的商店,其对商品种类管理使用的数据结构也是不相同的,有的是通过一个数组来存放,因为他们的店里永远只会卖固定种类的货物,然后有一些店里在不停的扩展规模,因此会通过一个可扩展的ArrayList来存放。(当然,现实中不会如此,为了举例方便)然后,现在各个商家给我数据了,而且不止这两种,这个时候头大了。

开始,这样来实现

public class Store{

//用来持有所有菜单条目
    public ArrayList<MenuItem>list = new ArrayList<MenuItem>();

    public Store(){

    }
//针对不同的商店创建不同的类型
    public void getFirstStoreMachines(FirstStoreMenu menu){
        MenuItem [] firstStoreMenu = menu.getMenuItems();
        for(int i=0; i<firstStoreMenu.length; i++)
            list.add(firstStoreMenu[i]);

    }

    public void getSecondStoreMachines(SecondStoreMenu menu){
        ArrayList<MenuItem> secondStoreMenu = menu.getMenuItems();
        for(int i=0; i<secondStoreMenu.size(); i++)
            list.add(secondStoreMenu.get(i));
    }
//用来展示所有的商品种类
    public void display(){
        for(int i=0; i<list.size(); i++){
            System.out.println(list.get(i).name);
        }
    }

}

针对每一个商店的数据集进行遍历,来获得菜单条目,如果有一百个商店,那么我们的代码量将变得很大,同时后期的维护也变得很困难了。

这个时候,又到了设计模式大显身手的时候了。通过迭代器模式来给数组和容器包上一层,使得其内部结构对外完全不可见,从而使得我们无需针对每种数据结构单独进行遍历操作。代码实例如下。
根据设计模式的基本原则针对接口编程,而不要针对具体类型,so

public interface Iterator{
    boolean hasNext();
    Object next();
}

看到这两个方法,获取sqlite数据库中的数据的既视感。
然后之前我们的商店菜单类是这样实现的

public class FirstStoreMenu extends Menu{
    MenuItem[] items;

    public MenuItem[] getFirstStoreMachines{
        return items;
    }
}

现在我们要使用迭代器了,所有要返回一个迭代器了,返回什么样的迭代器,这个迭代器具体要怎么实现呢?

public class FirstMenuIterator implements Iterator{
    MenuItem[] items;
    int position=0;

    public FirstMenuIterator(MenuItem[] items){
        this.items = items;
    }
//向下移动
    public Object next(){
        MenuItem menuItem  = items[position];
        position++;
        return menuItem;
    } 
//判断
    public boolean hasNext(){
        if(position>=items.length||items[position]==null){
            return false;
        }else{
            return true;
        }
    }
}
//通过判断和移动的结合实现我们需要的遍历操作

有了针对我们商店菜单的迭代器了,那么接下来可以这样写了

public class FirstStoreMenu extends Menu{
    MenuItem[]items;

    public Iterator createIterator(){
        return new FirstMenuIterator(items);
    }
}

我们总店中要如何应用这个迭代器呢?

public class Store{

//用来持有所有菜单条目
    public ArrayList<MenuItem>list = new ArrayList<MenuItem>();

    public Store(){

    }

    public void addItem(Iterator iterator){
        while(iterator.hasNext())
            list.add(iterator.next());
    }

//用来展示所有的商品种类
    public void display(){
        for(int i=0; i<list.size(); i++){
            System.out.println(list.get(i).name);
        }
    }

}

通过这种方式,我们不仅使得代码变得简洁(Store内的代码),同时也使得我们的编程针对接口再进行编程。使得store类对各商店菜单类的耦合变低。这样我们通过addItem方法向Store实例注入依赖实例即可完成对于各个商店的商品的汇总。

应用实例

上面提到了Android的数据库sqlite获得数据的时候,当然对于数据集的操作迭代器是很常用的。
Android中叫它游标,这个称呼更好的反应出了特性,在数据集之上游走。具体代码此处不再贴出。

边城大神,在文章中提到了一个桥接模式,对于这个模式,桥接模式其思想为,将对象和行为单独封装成类,对象的特征和行为松耦合,然后对象自身并不去实现行为,通过对委托的形式调用行为类,结构上比较像是策略模式的结构。

下篇更新生成器模式,结合Android中的AlertDialog.Builder来谈下

    原文作者:设计模式
    原文地址: https://segmentfault.com/a/1190000003834815
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞