Java设计模式——迭代器模式

迭代器模式的定义是:
  提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部表示
问题:
  这里引用《Head First》中的一个示例,如果一个聚合对象(菜单)中存在两种不同的存储结构(ArrayList & Array),该如何操作?
  如果是简单的逐个遍历,程序的扩展性就会很差, 如果再增加新的存储结构,就需要对代码进行大量的修改
解决办法:
  可以创建一个对象,将他称之为迭代器(Iterator),利用它来封装“遍历集合内每个对象的过程”,然后迭代器暗中根据容器的不同,使用不同的调用方法。
  
(这里可以这么理解,用迭代器去迭代,可以都调用next 和hasNext方法,然后在这两个方法中写具体的实现,这样我们如果要是需要新增存储结构的话,也只需要调用这两个方法,然后在对应的迭代器中去书写相应的迭代代码就可以了)
  这里先介绍一下Java中的迭代器,Java中的迭代器位于java.util.Iterator包下,是一个轻量级的对象,创建代价小,主要方法有
  1 hashNext (判断当前元素是否存在(不会移动指针)
  2 next(返回当前元素,并指向下一个元素)

使用迭代器的好处:
  1 提供了一种简单的遍历方式
  2 支持以不同的方式去遍历一个聚合对象(ArrayList和Array的遍历方式不同,但是使用迭代器可以遍历这两种存储结构组成的聚合对象)
  3 不会暴露内部实现细节
  4 解耦合
  5 具有扩展性,增加新的聚合类和迭代器都很方便,无需修改原有代码
例子代码实现:
Menu,提供通用的方法规范:

package spring.design.pattern.iterator;
 
import java.util.Iterator;
 
/**
 * Description:
 *
 * @author 慕容蓝
 * @version 1.0
 * @date 2018/11/27 17:09
 */
public interface Menu {
  Iterator createIterator();
}

菜单(数组),在这个类里,它会把数据存储的数据,交给迭代器进行处理

package spring.design.pattern.iterator;
 
import java.util.Iterator;
 
/**
 * Description:晚餐类.
 *
 * @author 慕容蓝
 * @version 1.0
 * @date 2018/11/27 15:05
 */
public class DinerMenu implements Menu{
  static final int Max_ITEMS = 6;
  int numberOfItems = 0;
  MenuItem[] menuItems;
 
  public DinerMenu() {
    menuItems = new MenuItem[Max_ITEMS];
    AddItem("红烧肉", "Braised pork", false, 10.5);
    AddItem("番茄炒蛋", "Tomato scrambled eggs", false, 8.5);
  }
 
  public void AddItem(String name, String description, Boolean vegetarian, double price) {
    MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
    if (numberOfItems > Max_ITEMS) {
      throw new RuntimeException("菜单已满");
    } else {
      menuItems[numberOfItems] = menuItem;
      numberOfItems++;
    }
  }
 
  @Override
  public Iterator createIterator(){
    return new DinerMenuIterator(menuItems);
  }
}

菜单(集合),同上

package spring.design.pattern.iterator;
 
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Iterator;
 
/**
 * Description:早餐类.
 *
 * @author 慕容蓝
 * @version 1.0
 * @date 2018/11/27 14:59
 */
public class PancakeHouseMenu implements Menu{
  ArrayList<MenuItem> menuItems;
 
  public PancakeHouseMenu() {
    menuItems = new ArrayList();
    AddItem("牛奶", "milk", false, 3.0);
    AddItem("面包", "bread", false, 1.0);
  }
 
  public void AddItem(String name, String description, Boolean vegetarian, double price) {
    MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
    menuItems.add(menuItem);
  }
 
  @Override
  public Iterator createIterator() {
    return menuItems.iterator();
  }
}

数组&集合中存储的对象:

package spring.design.pattern.iterator;
 
/**
 * Description:菜单类.
 *
 * @author 慕容蓝
 * @version 1.0
 * @date 2018/11/27 14:55
 */
public class MenuItem {
  private String name;
  private String description;
  private boolean vegetarin;
  private double price;
 
  public MenuItem(String name, String description, boolean vegetarin, double price) {
    this.name = name;
    this.description = description;
    this.vegetarin = vegetarin;
    this.price = price;
  }
 
  public double getPrice() {
    return price;
  }
 
  public String getName() {
    return name;
  }
 
  public String getDescription() {
    return description;
  }
 
  public boolean isVegetarin() {
    return vegetarin;
  }
}

数组的迭代器,这里重写了迭代器的三个方法hasNext next remove:

package spring.design.pattern.iterator;
 
import java.util.Iterator;
 
/**
 * Description:晚餐菜单迭代器.
 *
 * @author 慕容蓝
 * @version 1.0
 * @date 2018/11/27 15:23
 */
public class DinerMenuIterator implements Iterator {
 
  /** position记录当前数组遍历的位置 */
  int position = 0;
 
  MenuItem[] items;
 
  public DinerMenuIterator(MenuItem[] items) {
    this.items = items;
  }
 
  @Override
  public boolean hasNext() {
    if (position >= items.length || items[position] == null) {
      return false;
    }
    return true;
  }
 
  @Override
  public Object next() {
    MenuItem menuItem = items[position];
    position = position + 1;
    return menuItem;
  }
 
  @Override
  public void remove() {
    if (position <= 0) {
      throw new IllegalStateException("You can't remove an item you've done at least one next()");
    }
    if (items[position - 1] != null) {
      for (int i = position - 1; i < (items.length - 1); i++) {
        items[i] = items[i + 1];
      }
      items[items.length - 1] = null;
    }
  }
}

服务员类,负责打印数据:

package spring.design.pattern.iterator;

import java.util.Iterator;

/**
* Description:服务员类.
*
* @author muronglan
* @version 1.0
* @date 2018/11/27 15:30
*/
public class Waitress {
 /** init() */
 Menu pancakeHouseMenu ;

 Menu dinerMenu ;

 public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
   this.pancakeHouseMenu = pancakeHouseMenu;
   this.dinerMenu = dinerMenu;
 }

 public void printMenu() {
   Iterator pancakeIterator = pancakeHouseMenu.createIterator();
   Iterator dinerIterator = dinerMenu.createIterator();
   System.out.println("MENU\n --- \nBREAKFAST");
   printMenu(pancakeIterator);
   System.out.println("\nLUNCH");
   printMenu(dinerIterator);
 }

 public void printMenu(Iterator iterator) {
   while (iterator.hasNext()) {
     MenuItem menuItem = (MenuItem) iterator.next();
     System.out.println(menuItem.getName() + ",");
     System.out.println(menuItem.getPrice() + " --- ");
     System.out.println(menuItem.getDescription());
   }
 }
}

测试类,负责展现效果:

package spring.design.pattern.iterator;
 
/**
 * Description:测试类.
 *
 * @author 慕容蓝
 * @version 1.0
 * @date 2018/11/27 16:04
 */
public class Test {
  public static void main(String[] args) {
    PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
    DinerMenu dinerMenu = new DinerMenu();
    Waitress waitress = new Waitress(pancakeHouseMenu,dinerMenu);
    waitress.printMenu();
  }
}

找时间补上一张UML图

在Java代码中的集合中,也是使用到了迭代器
Collection接口,继承了Iteratable接口,该接口中的Iterator方法可以产生一个
Iterator对象:

public interface Collection<E> extends Iterable<E> {}
/**
 * Performs the given action for each element of the {@code Iterable}
 * until all elements have been processed or the action throws an
 * exception.  Unless otherwise specified by the implementing class,
 * actions are performed in the order of iteration (if an iteration order
 * is specified).  Exceptions thrown by the action are relayed to the
 * caller.
 *
 * @implSpec
 * <p>The default implementation behaves as if:
 * <pre>{@code
 *     for (T t : this)
 *         action.accept(t);
 * }</pre>
 *
 * @param action The action to be performed for each element
 * @throws NullPointerException if the specified action is null
 * @since 1.8
 */

大概意思是对{@code Iterable} 的每个元素执行给定操作,如果产生了异常,异常会被抛给调用者
  
然后使用Iterator就可以对Conllection中的元素进行迭代操作:

public interface Iterator<E> {
    /**
     * 判断当前元素是否存在(不会移动指针)
     */
    boolean hasNext();
 
    /**
     * 返回当前元素,并指向下一个元素
     */
    E next();}

我们可以通过增强型for循环去完成集合中的迭代,也可以自己去调用iterator方法,创建一个迭代器

package spring;
 
import java.util.ArrayList;
import java.util.List;
 
/**
 * Description:
 *
 * @author 慕容蓝
 * @version 1.0
 * @date 2018/11/27 11:52
 */
public class Test {
  public static void main(String[] args) {
    List<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    for (Integer i : list) {
      System.out.print(i);
    }
  }
}
package spring;

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

/**
* Description:
*
* @author 慕容蓝
* @version 1.0
* @date 2018/11/27 11:52
*/
public class Test {
 public static void main(String[] args) {
   List<Integer> list = new ArrayList<>();
   list.add(1);
   list.add(2);
   list.add(3);
   Iterator<Integer> iterator = list.iterator();
   while (iterator.hasNext()){
     System.out.println(iterator.next());
   }
 }
}

猜你喜欢

转载自blog.csdn.net/Kirito19970409/article/details/84570921