1. 程式人生 > >設計模式(十)—— 迭代器模式

設計模式(十)—— 迭代器模式

一、含義

提供一種方法順序訪問一個聚合物件中的各個元素,而又不暴露其內部的表示。當我們在專案中需要遍歷不同的集合、陣列時,可以考慮使用迭代器模式,提供一個統一的遍歷方法。

二、要點

1.迭代器將遍歷聚合的工作封裝進一個物件中。

2.迭代器提供一個通用的介面,讓我們遍歷聚合的項,當我們編碼使用聚合的項時,就可以使用多肽機制。

3.迭代器允許訪問聚合的元素,而不需要暴露它的內部結構。

三、實戰分析迭代器模式

先來看一下此設計模式的類圖

例如我們在維護一個專案的時候發現,在整個專案中存放物件集合,有的地方用的是陣列,有的地方用的是集合,當在一個物件中,需要遍歷的時候,就顯得非常麻煩,程式碼如下所示:

//利用陣列來存放物件
public class ArrayMenu {
    static final int MAX_ITEMS = 3;
    int numberItems = 0;
    Menu[] menus;

    public ArrayMenu() {
        menus = new Menu[MAX_ITEMS];
        addItem("牛肉漢堡",22.5);
        addItem("雞腿漢堡",15.0);
        addItem("烤雞腿",10.0);
    }
    
    public void addItem(String name, Double price) {
        Menu menu = new Menu(name, price);
        if (numberItems > MAX_ITEMS) {
            System.out.println("陣列已滿,無法新增");
        } else {
            menus[numberItems] = menu;
            numberItems ++;
        }
        
    }

    public Menu[] getMenus() {
        return menus;
    }
}


//用List集合來存放物件
public class ListMenu {

    ArrayList menuItems;

    public ListMenu() {
        menuItems = new ArrayList();
        addItem("西紅柿雞蛋",12.5);
        addItem("土豆絲",10.0);
        addItem("紅燒肉",30.5);

    }

    public void addItem(String name, Double price) {
        Menu menu = new Menu(name, price);
        menuItems.add(menu);
    }

    public ArrayList getMenuItems() {
        return menuItems;
    }
}

當我需要在一個類裡需要同時遍歷時,程式碼就很顯得很重複

public class ListArrayTest {
    ListMenu listMenu = new ListMenu();
    ArrayMenu arrayMenu = new ArrayMenu();

    ArrayList menuItems = listMenu.getMenuItems();
    Menu[] menus = arrayMenu.getMenus();
    
    
    public void getMenu() {
        for (int i = 0; i < menuItems.size(); i++) {
            Menu menu = (Menu) menuItems.get(i);
            System.out.println(menu.getName() + " ");
            System.out.println(menu.getPrice() + " ");
            
        }

        for (int i = 0; i < menus.length; i++) {
            Menu menu = menus[i];
            System.out.println(menu.getName() + "");
            System.out.println(menu.getPrice() + "");
        }
    }
}

這個時候我們的迭代器模式就要閃亮登場了,首先我們定義一個迭代器介面:

//定義一個迭代器介面
public interface Iterator {
    
    //判斷是否有更多的元素
    boolean hasNext();
    
    //返回下一個元素
    Object next();
    
}

然後實現一個具體的迭代器方法:

public class MenuIterator implements Iterator {
    
    Menu[] menus;
    int position = 0;

    public MenuIterator(Menu[] menus) {
        this.menus = menus;
    }

    @Override
    public boolean hasNext() {
        if (position >= menus.length || menus[position] == null) {
            return false;
        } else {
            return true;
        } 
        
    }

    @Override
    public Object next() {
        Menu menu = menus[position];
        position ++;
        return menu;
    }
}

然後我們就可以改造我們之間的程式碼了:

 //加入一個建立構造器的方法即可
 public Iterator createIterator() {
        return new MenuIterator(menus);
 }

這個時候在編寫我們的測試類:

public class ListArrayTest {
    ListMenu listMenu = new ListMenu();
    ArrayMenu arrayMenu = new ArrayMenu();

    
    public void getIterator() {
        Iterator MenuIterator = arrayMenu.createIterator();
        Iterator ListIterator = listMenu.createIterator();
    }
    
    
    private void printMenu(Iterator iterator) {
        while (iterator.hasNext()) {
            Menu menu = (Menu) iterator.next();
            System.out.println(menu.getName() + " ");
            System.out.println(menu.getPrice() + " ");
        }
        
    }
}

程式碼看上去就簡潔了許多,測試結果:

西紅柿雞蛋 
12.5 
土豆絲 
10.0 
紅燒肉 
30.5 
牛肉漢堡
22.5
雞腿漢堡
15.0
烤雞腿
10.0

文章內容參考《Head First 設計模式》