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

来源:互联网 发布:21端口被占用 编辑:程序博客网 时间:2024/06/10 05:06

     迭代器模式

提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

迭代器模式把在元素之间游走的责任交给了迭代器,而不是聚合对象。这不仅让聚合的接口和实现变得更简洁,也可以让聚合更专注在它所应该专注的事情上面(也就是管理对象集合),而不必去理会遍历的事情。

        下面是具体例子:

菜单项的类:MenuItem.java

[java] view plaincopy
  1. package com.designpattern.iterator;  
  2.   
  3. public class MenuItem {  
  4.     String name;  
  5.     String description;  
  6.     boolean vegetarian;  
  7.     double price;  
  8.       
  9.     public MenuItem(String name,  
  10.                     String description,  
  11.                     boolean vegetarian,  
  12.                     double price){  
  13.         this.name = name;  
  14.         this.description = description;  
  15.         this.vegetarian = vegetarian;  
  16.         this.price = price;  
  17.     }  
  18.   
  19.     public String getName() {  
  20.         return name;  
  21.     }  
  22.   
  23.     public String getDescription() {  
  24.         return description;  
  25.     }  
  26.   
  27.     public boolean isVegetarian() {  
  28.         return vegetarian;  
  29.     }  
  30.   
  31.     public double getPrice() {  
  32.         return price;  
  33.     }  
  34.   
  35. }  

菜单的共同接口(用于返回迭代器):Menu.java

[java] view plaincopy
  1. package com.designpattern.iterator;  
  2.   
  3. import java.util.Iterator;  
  4.   
  5. /** 
  6.  * 菜单的共同接口 
  7.  * */  
  8. public interface Menu {  
  9.     public Iterator<?> createIterator();  
  10. }  

建立两个菜单:PancakeHouseMenu.java & DinerMenu.java,都实现Menu接口

[java] view plaincopy
  1.   
[java] view plaincopy
  1. package com.designpattern.iterator;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Iterator;  
  5.   
  6. /** 
  7.  * 用ArrayList来存储菜单项,有内嵌的返回迭代器方法,menuItems.iterator(); 
  8.  * createIterator()方法中可以直接返回迭代器,不用自己写迭代器; 
  9.  * */  
  10. public class PancakeHouseMenu implements Menu{  
  11.     ArrayList<MenuItem> menuItems;  
  12.       
  13.     public PancakeHouseMenu(){  
  14.         menuItems = new ArrayList<MenuItem>();  
  15.           
  16.         addItem("K&B's 薄煎饼早餐""薄煎饼、清蛋和吐司"true2.99);  
  17.         addItem("薄煎饼早餐例餐""薄煎饼带煎蛋,香肠"false2.99);  
  18.         addItem("蓝莓薄煎饼""新鲜蓝莓和蓝莓糖浆做成的薄煎饼"true3.49);  
  19.         addItem("松饼""松饼,可以选择蓝莓或草莓"true3.59);  
  20.     }  
  21.       
  22.     public void addItem(String name, String description,   
  23.                         boolean vegetarian, double price){  
  24.         MenuItem menuItem = new MenuItem(name, description, vegetarian, price);  
  25.         menuItems.add(menuItem);  
  26.     }  
  27.       
  28. //  public ArrayList<MenuItem> getMenuItems(){  
  29. //      return menuItems;  
  30. //  }  
  31.   
  32.     @Override  
  33.     public Iterator<MenuItem> createIterator() {  
  34.         // TODO Auto-generated method stub  
  35.         return menuItems.iterator();  
  36.     }  
  37.   
  38. }  


[java] view plaincopy
  1. package com.designpattern.iterator;  
  2.   
  3. import java.util.Iterator;  
  4.   
  5. /** 
  6.  * 用数组来存储菜单项,没有内嵌的返回迭代器方法; 
  7.  * 需要自己写迭代器:DinerMenuIterator.java,继承自Iterator类。 
  8.  * */  
  9. public class DinerMenu implements Menu{  
  10.     static final int MAX_ITEMS = 6;  
  11.     int numberOfItems = 0;  
  12.     MenuItem[] menuItems;  
  13.       
  14.     public DinerMenu(){  
  15.         menuItems = new MenuItem[MAX_ITEMS];  
  16.           
  17.         addItem("素食BLT""(煎)培根、生菜&西红柿,用麦皮面包做"true2.99);  
  18.         addItem("BLT""培根、生菜&西红柿"false2.99);  
  19.         addItem("例汤""一碗例汤,配土豆沙拉"false3.29);  
  20.         addItem("热狗""热狗、酸菜、上盖芝士"false3.05);  
  21.     }  
  22.       
  23.     public void addItem(String name,String description,   
  24.                     boolean vegetarian, double price){  
  25.         MenuItem menuItem = new MenuItem(name, description, vegetarian, price);  
  26.         if(numberOfItems >= MAX_ITEMS){  
  27.             System.err.println("Sorry, menu is full! Can't add item to menu.");  
  28.         }else{  
  29.             menuItems[numberOfItems] = menuItem;  
  30.             numberOfItems +=1;  
  31.         }  
  32.     }  
  33.       
  34. //  public MenuItem[] getMenuItems(){  
  35. //      return menuItems;  
  36. //  }  
  37.   
  38.     @Override  
  39.     public Iterator<Object> createIterator() {  
  40.         // TODO Auto-generated method stub  
  41.         return new DinerMenuIterator(menuItems);  
  42.     }  
  43. }  


DinerMenu.java中用到的返回迭代器的类:DinerMenuIterator.java

[java] view plaincopy
  1. package com.designpattern.iterator;  
  2.   
  3. import java.util.Iterator;  
  4.   
  5. /** 
  6.  * 由于数组没有内嵌的返回迭代器的方法,因此需要写自己的迭代器; 
  7.  * */  
  8. public class DinerMenuIterator implements Iterator<Object>{  
  9.     MenuItem[] list;  
  10.     int position = 0;  
  11.       
  12.     public DinerMenuIterator(MenuItem[] list){  
  13.         this.list = list;  
  14.     }  
  15.       
  16.     @Override  
  17.     public boolean hasNext() {  
  18.         // TODO Auto-generated method stub  
  19.         if(position >= list.length || list[position] == null){  
  20.             return false;  
  21.         }else{  
  22.             return true;  
  23.         }  
  24.     }  
  25.   
  26.     @Override  
  27.     public Object next() {  
  28.         // TODO Auto-generated method stub  
  29.         MenuItem menuItem = list[position];  
  30.         position += 1;  
  31.         return menuItem;  
  32.     }  
  33.   
  34.     @Override  
  35.     public void remove() {  
  36.         // TODO Auto-generated method stub  
  37.         if(position <= 0){  
  38.             throw new IllegalStateException("You can't remove an item until you've done at least one next().");  
  39.         }  
  40.         if(list[position - 1] != null){  
  41.             for(int i = position-1;i<(list.length -1);i++){  
  42.                 list[i] = list[i+1];  
  43.             }  
  44.             list[list.length-1] = null;  
  45.         }  
  46.     }  
  47.   
  48. }  

具体操作菜单的类:Waitress.java

[java] view plaincopy
  1. package com.designpattern.iterator;  
  2.   
  3. import java.util.Iterator;  
  4.   
  5. /** 
  6.  * 操作菜单的类  
  7.  * */  
  8. public class Waitress {  
  9.     Menu pancakeHouseMenu;  
  10.     Menu dinerMenu;  
  11.       
  12.     public Waitress(Menu pancakeHouseMenu, Menu dinerMenu){  
  13.         this.pancakeHouseMenu = pancakeHouseMenu;  
  14.         this.dinerMenu = dinerMenu;  
  15.     }  
  16.       
  17.     public void printMenu(){  
  18.         Iterator<?> pancakeIterator = pancakeHouseMenu.createIterator();   
  19.         Iterator<?> dinerIterator = dinerMenu.createIterator();  
  20.         System.out.println("MENU\n----\nBREAKFAST");  
  21.         printMenu(pancakeIterator);  
  22.         System.out.println("\nLUNCH");  
  23.         printMenu(dinerIterator);  
  24.     }  
  25.       
  26.     private void printMenu(Iterator<?> iterator){  
  27.         while(iterator.hasNext()){  
  28.             MenuItem menuItem = (MenuItem) iterator.next();  
  29.             System.out.println(menuItem.getName() + ",");  
  30.             System.out.println(menuItem.getPrice() + "---");  
  31.             System.out.println(menuItem.getDescription());  
  32.         }  
  33.     }  
  34. }  

测试类:Test.java

[java] view plaincopy
  1. package com.designpattern.iterator;  
  2.   
  3. public class Test {  
  4.     public static void main(String[] args) {  
  5.         Menu pancakeHouseMenu = new PancakeHouseMenu();  
  6.         Menu dinerMenu = new DinerMenu();  
  7.           
  8.         Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);  
  9.         waitress.printMenu();  
  10.     }  
  11. }  


        小结:

        两个菜单都实现了Menu接口,Waitress类可以直接利用接口引用每一个菜单对象。这样通过“针对接口编程,而不是针对实现编程”,我们就可以减少Waitress类与具体类之间的依赖。

       此外,如果想要再添加新的菜单也会变得很容易,只需要按照前面两个菜单类写一个继承Menu接口的菜单类,再在Waitress类中添加菜单类的对象即可。即Waitress类具有更好的扩展性。

       JAVA 5包含了一种新形式的for语句,称for/in。这可以让你在一个集合或者一个数组中遍历,而且不需要显式创建迭代器。但需要使用JAVA 5的泛型新特性来确保for/in的类型安全。

       但是,迭代器模式还存在一个问题,假如想在菜单中添加子菜单,迭代器模式是不可以实现的。

0 0
原创粉丝点击