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<T> {

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

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

package iterator;

public interface Order extends Iterable<Item>{

}

注意上面的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<Item> list = new ArrayList<Item>();

 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<Item> iterator() {
 return new MyIterator();
 }

 private class MyIterator implements Iterator<Item> {

 private Iterator<Item> 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<orders.length;i++){
  newItems[i]=orders[i];
 }
 orders=newItems;
 }

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

 private class MyIterator implements Iterator<Item>{

 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方法,然后实现自己的迭代方式。

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

(0)

相关推荐

  • java集合迭代器Iterator中的remove陷阱

    package TestList; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.TreeSet; public class TestIterator { /**      * @param args      */     public static void main(String[] args) {         // TODO Auto-gen

  • java 中迭代器的使用方法详解

    java 中迭代器的使用方法详解 前言: 迭代器模式将一个集合给封装起来,主要是为用户提供了一种遍历其内部元素的方式.迭代器模式有两个优点:①提供给用户一个遍历的方式,而没有暴露其内部实现细节:②把元素之间游走的责任交给迭代器,而不是聚合对象,实现了用户与聚合对象之间的解耦. 迭代器模式主要是通过Iterator接口来管理一个聚合对象的,而用户使用的时候只需要拿到一个Iterator类型的对象即可完成对该聚合对象的遍历.这里的聚合对象一般是指ArrayList,LinkedList和底层实现为数

  • 详解Java中Iterator迭代器的用法

    迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为"轻量级"对象,因为创建它的代价小. Java中的Iterator功能比较简单,并且只能单向移动: (1) 使用方法iterator()要求容器返回一个Iterator.第一次调用Iterator的next()方法时,它返回序列的第一个元素.注意:iterator()方法是java.lang.Iterable接口,被Collection继承

  • Java实现的自定义迭代器功能示例

    本文实例讲述了Java实现的自定义迭代器功能.分享给大家供大家参考,具体如下: 编写自己的Iterator,实现Iterator接口,这里多说一句,实现Iterable后,可以用"foreach"循环遍历你的对象. import java.util.Iterator; import java.util.NoSuchElementException; /** * 演示Iterator和Iterable接口,并说明怎样编写一个用于对象数组的简单迭代器. */ public class Aa

  • Java Iterator迭代器_动力节点Java学院整理

    迭代器是一种模式,它可以使得对于序列类型的数据结构的遍历行为与被遍历的对象分离,即我们无需关心该序列的底层结构是什么样子的.只要拿到这个对象,使用迭代器就可以遍历这个对象的内部. 1.Iterator Java提供一个专门的迭代器<<interface>>Iterator,我们可以对某个序列实现该interface,来提供标准的Java迭代器.Iterator接口实现后的功能是"使用"一个迭代器. 文档定义: Package java.util; publici

  • 详解Java中的迭代迭代器Iterator与枚举器Enumeration

    迭代器Iterator接口 1.迭代器接口 Iterable 内置方法iterator(), 返回一个新建的 Iterator. 如: public interface Iterable { Iterator Iterator(); } Iterator 有 hasNext() 和 next() 两个方法要实现. public interface Iterator { boolean hasNext(); Item next(); void remove(); //可选实现 } 2.实现 导入

  • java 迭代器模式实例详解

    java 迭代器模式实例详解 今天来818设计模式中的迭代器模式,也是java中Stack,List,Set等接口以及数组这个数据结构都会使用的一种模式. 首先,为什么使用迭代器模式,目的就是通过一个通用的迭代方法,隐藏stack,list,set以及数组中不同的遍历细节.也就是说,我不想让那些调用我的遍历容器的方法的人知道我到底是怎么一个一个的获取这些元素的(stack的pop,list的get,数组的array[i]),我只想让他知道他能 通过一个迭代器Iterator或者通过一个for e

  • Java桥接模式实例详解【简单版与升级版】

    本文实例讲述了Java桥接模式.分享给大家供大家参考,具体如下: 桥接模式简单版 一 代码 class Meal { protected MealImp imp; public Meal() { imp = new AmericanMealImp(); } public Meal(String type) { if (type.equals("American")) imp = new AmericanMealImp(); if (type.equals("Italian&q

  • Java代理模式实例详解【静态代理与动态代理】

    本文实例讲述了Java代理模式.分享给大家供大家参考,具体如下: 即Proxy Pattern,23种java常用设计模式之一.代理模式的定义:对其他对象提供一种代理以控制对这个对象的访问. Java的代理模式是Java中比较常用的设计模式,分为2中代理:静态代理与动态代理(JDK动态代理和cglib动态代理) 优点: 职责清晰 真实角色只需关注业务逻辑的实现,非业务逻辑部分,后期通过代理类完成即可. 高扩展性 不管真实角色如何变化,由于接口是固定的,代理类无需做任何改动. 缺点: 很明显的一点

  • Java List 用法实例详解

    Java List 用法实例详解 Java中可变数组的原理就是不断的创建新的数组,将原数组加到新的数组中,下文对Java List用法做了详解. List:元素是有序的(怎么存的就怎么取出来,顺序不会乱),元素可以重复(角标1上有个3,角标2上也可以有个3)因为该集合体系有索引 ArrayList:底层的数据结构使用的是数组结构(数组长度是可变的百分之五十延长)(特点是查询很快,但增删较慢)线程不同步 LinkedList:底层的数据结构是链表结构(特点是查询较慢,增删较快) Vector:底层

  • JS设计模式之责任链模式实例详解

    本文实例讲述了JS设计模式之责任链模式.分享给大家供大家参考,具体如下: 责任链设计模式: 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任. 责任链模式涉及到的角色如下所示: ● 抽象处理者(Handler)角色:定义出一个处理请求的接口.如果需要,接口可以定义 出一个方法以设定和返回对下家的引

  • Java多线程ForkJoinPool实例详解

    引言 java 7提供了另外一个很有用的线程池框架,Fork/Join框架 理论 Fork/Join框架主要有以下两个类组成. * ForkJoinPool 这个类实现了ExecutorService接口和工作窃取算法(Work-Stealing Algorithm).它管理工作者线程,并提供任务的状态信息,以及任务的执行信息 * ForkJoinTask 这个类是一个将在ForkJoinPool执行的任务的基类. Fork/Join框架提供了在一个任务里执行fork()和join()操作的机制

  • java 抽象类的实例详解

    java 抽象类的实例详解 前言: 什么是抽象类?这名字听着就挺抽象的,第一次听到这个名字还真有可能被唬住.但是,就像老人家所说的,一切反动派都是纸老虎,一切有着装x名字的概念也是纸老虎.好吧,我们已经从战略上做到了藐视它,现在就要战术上重视它,如同要解决纸老虎,就要一个牙齿一个牙齿地敲,一个爪子一个爪子地拔:解决这种抽象概念也一样,先要把它具体化,细分化,然后一个一个地来. 我一般遇到新的概念都会问三个问题: 1.这个东西有什么用?用来干什么的?它的意义在哪里?(显然,如果是没用的东西,就没必

  • Java 多线程优先级实例详解

    Java 多线程优先级实例详解 线程的优先级将该线程的重要性传递给调度器.尽管CPU处理现有线程集的顺序是不确定的,但是调度器将倾向于让优先权最高的线程先执行. 你可以用getPriority()来读取现有线程的优先级,并且在任何时刻都可以通过setPriority()来修改优先级. import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class SimplePrio

  • java LinkedList的实例详解

    java LinkedList的实例详解 站在Java的角度看,玩队列不就是玩对象引用对象嘛! 实例代码: public class LinkedList<E> implements List<E>, Deque<E> { Node<E> first; Node<E> last; int size; public boolean add(E e) { final Node<E> l = last; final Node<E>

  • Java 反射机制实例详解

    Java 反射机制实例详解 一.JAVA是动态语言吗? 一般而言,说到动态言,都是指在程序运行时允许改变程序结构或者变量类型,从这个观点看,Java和C++一样,都不是动态语言. 但JAVA它却有着一个非常突出的动态相关机制:反射.通过反射,Java可以于运行时加载.探知和使用编译期间完全求和的类.生成其对象实体,调用其方法或者对属性设值.所以Java算是一个半动态的语言吧. 反射的概念: 在Java中的反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; 对于任意一个对

随机推荐