当前位置: 首页 > news >正文

设计模式(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来谈下

相关文章:

  • Java对多线程~~~Fork/Join同步和异步帧
  • Percona MySQL编译安装到CentOS6.5
  • MySQL 优化(memcache)
  • VS 远程发布IIS
  • KVM - virsh常用操作
  • SQL Server对比两字段的相似度(函数算法)
  • 成功部署SSIS中含有Oracle数据库连接的ETL包
  • ios申请真机调试( xcode 5)详细解析
  • 国家气象局免费天气预报接口,城市代码(JSON格式)
  • 第四次作业 合同管理、配置管理和外包管理
  • Git 1.9.5.msysgit.1
  • ​Java并发新构件之Exchanger
  • 本地管理员密码解决方案 Local Admin Password Solution (LAPS)
  • 自适应电脑、手机和iPad的网页设计方法
  • 团队博客作业Week4 --- 学霸网站--NABC
  • “大数据应用场景”之隔壁老王(连载四)
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • 「译」Node.js Streams 基础
  • 345-反转字符串中的元音字母
  • create-react-app做的留言板
  • FineReport中如何实现自动滚屏效果
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • PAT A1050
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • webpack入门学习手记(二)
  • 浮动相关
  • 基于webpack 的 vue 多页架构
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 聊聊flink的BlobWriter
  • 如何学习JavaEE,项目又该如何做?
  • 深入 Nginx 之配置篇
  • 学习ES6 变量的解构赋值
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • linux 淘宝开源监控工具tsar
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ###C语言程序设计-----C语言学习(6)#
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (23)Linux的软硬连接
  • (办公)springboot配置aop处理请求.
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (十一)手动添加用户和文件的特殊权限
  • (四)Linux Shell编程——输入输出重定向
  • (一)Java算法:二分查找
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • .describe() python_Python-Win32com-Excel
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET 设计一套高性能的弱事件机制
  • .net 托管代码与非托管代码
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • [BUG] Hadoop-3.3.4集群yarn管理页面子队列不显示任务