热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

java迭代器模式实例详解

这篇文章主要介绍了java迭代器模式实例详解的相关资料,需要的朋友可以参考下

java 迭代器模式实例详解

今天来818设计模式中的迭代器模式,也是java中Stack,List,Set等接口以及数组这个数据结构都会使用的一种模式。

首先,为什么使用迭代器模式,目的就是通过一个通用的迭代方法,隐藏stack,list,set以及数组中不同的遍历细节。也就是说,我不想让那些调用我的遍历容器的方法的人知道我到底是怎么一个一个的获取这些元素的(stack的pop,list的get,数组的array[i]),我只想让他知道他能 通过一个迭代器Iterator或者通过一个for each语句就能拿到我容器里面所有的元素。这样就能够最大化的隐藏实现细节,封装变化了。

先通过一个例子来一步步了解这其中的重要性吧。比方说,我要开发一个平台,这个平台会获取到京东的订单和淘宝的订单,然后把订单中的所有购买条目全部打印出来。

既然要打印订单中的所有条目,那么就得先知道这些条目,也就是订单项有哪些属性。

package iterator;

/**
 * 
* @ClassName: Item 
* @Description: 订单项
* @author minjun
*
 */
public class Item {

 /**商品名称*/
 private String name;
 
 /**价格*/
 private double price;
 
 /**描述*/
 private String desc;
 
 /**数量*/
 private int count;

 public Item(String name, double price, String desc, int count) {
 this.name = name;
 this.price = price;
 this.desc = desc;
 this.count = count;
 }

 public String getName() {
 return name;
 }

 public void setName(String name) {
 this.name = name;
 }

 public double getPrice() {
 return price;
 }

 public void setPrice(double price) {
 this.price = price;
 }

 public String getDesc() {
 return desc;
 }

 public void setDesc(String desc) {
 this.desc = desc;
 }

 public int getCount() {
 return count;
 }

 public void setCount(int count) {
 this.count = count;
 }

 @Override
 public String toString() {
 return "Item [name=" + name + ", price=" + price + ", desc=" + desc
  + ", count=" + count + "]";
 }
}

知道了这个条目,然后我想看看京东和淘宝是如何存储这些条目的。于是我问了问刘强东和马云,得知京东是用集合List存储,因为方便,而淘宝是用数组存储,因为看起来更装逼。他们都不愿意修改存储的容器,因为改动太大。

这时, 如果用传统想法,ok,我拿到京东的List,然后通过for循环和list.get(i)获取里面的每个条目并打印。然后拿到淘宝的array,通过for循环和array[i]获取里面的条目并打印。是不是可以实现呢?确实可以,但是我发现这样的话,每个容器我都要实现一遍不同的打印方法。目前是两个倒还好,如果又来个谁谁谁,用链表来实现容器,那我是不是又要新加一个迭代链表的方法呢?我当然不会愿意,因为这样太麻烦了。于是乎,我有个想法,思路是这样的:

我希望让京东的订单和淘宝的订单都是可以方便的遍历里面的元素,遍历的方法能够通过一个公共的方法来处理,而不是像之前那个分别做处理。根据这个思路,用TDD(测试驱动开发)来做步骤实现。先写好测试代码,首先我要有个订单接口,里面有两个子类订单(淘宝订单和京东订单):

package iterator;

import org.junit.Test;

public class TestCase {

 @Test
 public void test() {
 Order o = 
  new TBOrder();//淘宝的订单
//  new JDOrder();//京东的订单
 printOrder(o);//打印订单

 }

 /**打印订单 */
 private void printOrder(Order o) {
 for (Item item : o) {
  System.out.println(item);
 }
 }
}

如果能像上述这样打印,那会多么方便啊。如果换成淘宝订单,就用淘宝的订单迭代实现,换成京东的订单,就用京东的订单实现,我在测试代码根本不需要关注实现细节。现在我会想,如果能通过什么方法直接打印这个订单Order中的所有条目,那才能完整的实现我上述的代码。也就是说我需要我的订单是可以遍历的,那应该怎么做呢?其实java中提供了这样的接口,就是Iterable,如果我的订单都实现了这个接口,那么我的订单自然而然就可以通过一个for each循环来遍历里面的内容。

/*
 * %W% %E%
 *
 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package java.lang;

import java.util.Iterator;

/** Implementing this interface allows an object to be the target of
 * the "foreach" statement.
 * @since 1.5
 */
public interface Iterable {

  /**
   * Returns an iterator over a set of elements of type T.
   * 
   * @return an Iterator.
   */
  Iterator iterator();
}

上面是java的Iterable接口,下面是我自己的订单接口,继承了Iterable接口

package iterator;

public interface Order extends Iterable{

}

注意上面的Order订单接口继承了Iterable接口之后,同样也继承过来了一个抽象方法iterator。这个抽象方法才是Iterable的根本实现方案。我们会在子类订单中分别实现这个接口,然后提供京东和淘宝不同的迭代方案。

京东

package iterator;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 
 * @ClassName: JDOrder
 * @Description: 京东订单
 * @author minjun
 * 
 */
public class JDOrder implements Order {

 /** 京东用集合装订单项 */
 private List list = new ArrayList();

 public JDOrder() {
 add("iphone6", 5000.00, "一部手机", 2);
 add("mbp", 16000.00, "一台电脑", 1);
 add("西门子洗衣机", 3000.00, "一台洗衣机", 3);
 }

 /** 添加订单条目 */
 public void add(String name, double price, String desc, int count) {
 list.add(new Item(name, price, desc, count));
 }

 @Override
 public Iterator iterator() {
 return new MyIterator();
 }

 private class MyIterator implements Iterator {

 private Iterator it = list.iterator();

 @Override
 public boolean hasNext() {
  return it.hasNext();
 }

 @Override
 public Item next() {
  return it.next();
 }

 @Override
 public void remove() {
  throw new UnsupportedOperationException("目前不支持删除操作");
 }

 }
}

淘宝

package iterator;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * 
* @ClassName: TBOrder 
* @Description: 淘宝订单 
* @author minjun
*
 */
public class TBOrder implements Order{
 
 private int size=3;

 private Item[] orders=new Item[size];
 
 private int index=0;
 
 public TBOrder(){
 add("天猫1", 1111, "天猫活动1", 1);
 add("天猫2", 1111, "天猫活动1", 1);
 add("天猫3", 1111, "天猫活动1", 1);
 add("天猫4", 1111, "天猫活动1", 1);
 add("天猫5", 1111, "天猫活动1", 1);
 add("天猫6", 1111, "天猫活动1", 1);
 add("天猫7", 1111, "天猫活动1", 1);
 add("天猫8", 1111, "天猫活动1", 1);
 }
 
 /**添加订单条目*/
 public void add(String name, double price, String desc, int count) {
 
 //如果超过数组大小,就扩容
 if(index>=size-1){
  resize();
 }
  
 orders[index++]=new Item(name, price, desc, count);
 }
 
 /**扩容*/
 private void resize() {
 size=size<<1;//移位运算符--相当于size=size*2
 Item[] newItems=new Item[size];
 //将原始数组内容拷贝到新数组中去
 for(int i=0;i iterator() {
 return new MyIterator();
 }
 
 private class MyIterator implements Iterator{
 
 private int curr=0;

 @Override
 public boolean hasNext() {
  return orders[curr]!=null;
 }

 @Override
 public Item next() {
  if(hasNext()){
  return orders[curr++];
  }else{
  throw new NoSuchElementException("没有这个元素");
  }
 }

 @Override
 public void remove() {
  throw new UnsupportedOperationException("目前不支持删除操作");
 }
 
 }

}

这样,我就做到了提供一个标准的可以迭代的Order订单接口,然后以两种不同的迭代实现方案(京东、淘宝),为我们的测试类提供了一个可以屏蔽掉内部不同容器的具体实现区别。同时,这也是迭代器模式的运用。

总结:需求--不同容器不同迭代方案,改进--利用相同迭代方案来处理,将不同实现细节分别隐藏到容器自己的实现中。采用的方案就是实现Iterable接口,以及里面的Iterator方法,然后实现自己的迭代方式。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!


推荐阅读
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 斯诺登质疑FBI要求苹果解锁iPhone的真实意图
    爱德华·斯诺登对FBI要求苹果解锁iPhone一事表示质疑,称其完全是扯谈。斯诺登在一次峰会上发表了自己的看法,并分享了一篇揭穿FBI真实企图的文章。他认为这场战役将是未来十年内最重大的科技案件。斯诺登对于监控隐私问题非常敢于发表意见。 ... [详细]
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
  • 在2022年,随着信息化时代的发展,手机市场上出现了越来越多的机型选择。如何挑选一部适合自己的手机成为了许多人的困扰。本文提供了一些配置及性价比较高的手机推荐,并总结了选择手机时需要考虑的因素,如性能、屏幕素质、拍照水平、充电续航、颜值质感等。不同人的需求不同,因此在预算范围内找到适合自己的手机才是最重要的。通过本文的指南和技巧,希望能够帮助读者节省选购手机的时间。 ... [详细]
  • 本文介绍了使用Python编写购物程序的实现步骤和代码示例。程序启动后,用户需要输入工资,并打印商品列表。用户可以根据商品编号选择购买商品,程序会检测余额是否充足,如果充足则直接扣款,否则提醒用户。用户可以随时退出程序,在退出时打印已购买商品的数量和余额。附带了完整的代码示例。 ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • macOS Big Sur全新设计大版本更新,10+个值得关注的新功能
    本文介绍了Apple发布的新一代操作系统macOS Big Sur,该系统采用全新的界面设计,包括图标、应用界面、程序坞和菜单栏等方面的变化。新系统还增加了通知中心、桌面小组件、强化的Safari浏览器以及隐私保护等多项功能。文章指出,macOS Big Sur的设计与iPadOS越来越接近,结合了去年iPadOS对鼠标的完善等功能。 ... [详细]
  • 本文介绍了iPhone降频开关的位置和设置方法,以及解释了内存中的其他文件的含义和清理方法。同时提醒用户,在内存不足时系统会自动删除这些文件来腾出容量,因此不必过于担心。 ... [详细]
  • 爱奇艺如何使用扫码登录二维码
    本文介绍了在使用爱奇艺时如何通过扫码登录二维码的具体操作方法,包括打开爱奇艺app、点击“我的”按钮、点击扫码按钮等步骤。同时提供了操作环境的相关信息,包括手机品牌型号、系统版本和软件版本。 ... [详细]
  • 本文介绍了互联网思维中的三个段子,涵盖了餐饮行业、淘品牌和创业企业的案例。通过这些案例,探讨了互联网思维的九大分类和十九条法则。其中包括雕爷牛腩餐厅的成功经验,三只松鼠淘品牌的包装策略以及一家创业企业的销售额增长情况。这些案例展示了互联网思维在不同领域的应用和成功之道。 ... [详细]
  • Unity3D引擎的体系结构和功能详解
    本文详细介绍了Unity3D引擎的体系结构和功能。Unity3D是一个屡获殊荣的工具,用于创建交互式3D应用程序。它由游戏引擎和编辑器组成,支持C#、Boo和JavaScript脚本编程。该引擎涵盖了声音、图形、物理和网络功能等主题。Unity编辑器具有多语言脚本编辑器和预制装配系统等特点。本文还介绍了Unity的许可证情况。Unity基本功能有限的免费,适用于PC、MAC和Web开发。其他平台或完整的功能集需要购买许可证。 ... [详细]
  • 本文介绍了iOS开发中检测和解决内存泄漏的方法,包括静态分析、使用instruments检查内存泄漏以及代码测试等。同时还介绍了最能挣钱的行业,包括互联网行业、娱乐行业、教育行业、智能行业和老年服务行业,并提供了选行业的技巧。 ... [详细]
  • Python教学练习二Python1-12练习二一、判断季节用户输入月份,判断这个月是哪个季节?3,4,5月----春 ... [详细]
  • 转化率低?应该这样做数据分析!
    在互联网业务中,转化率无处不在:投放转化率:有多少人从广告链接,进到我们的商品页面?购买转化率: ... [详细]
  • 苹果手机home键设置1.我们点击打开iPhone手机桌面上的设置图标。2.点击打开页面中的通用选项。 ... [详细]
author-avatar
Scarlett_girl
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有