開發之路(設計模式十:迭代器模式上)

有許多種方法能夠把對象堆起來成爲一個集合

好消息,當地的餐廳和煎餅屋合併了,可是二者實現的方式卻不一樣,這就形成了分歧。讓咱們一塊兒去看看把。
圖片描述
圖片描述java

一個使用ArrayList集合,另外一個使用數組實現,事情看起來確實棘手,咱們建立一個女招待做爲中間人來使用兩個菜單的客戶代碼
圖片描述編程

這裏就有個問題,咱們在打印早餐和午飯的時候因爲使用對象不一樣,Arraylist和數組,這樣咱們就要寫兩個for循環了,假若後面還有新的對象加進來作晚餐呢?或許咱們能想出一個辦法,讓他們的菜單實現一個相同的接口,咱們是否能夠試着封裝多個遍歷呢?步驟圖以下
圖片描述
圖片描述設計模式

OK,看來迭代器模式幫助了咱們,迭代器(iterator)依賴於迭代器接口。相關類圖以下
圖片描述數組

想要在餐廳菜單中加入迭代器,咱們先定義迭代器接口ide

package MenuItem;

/**
 * 迭代器接口
 * 
 * @author Joy
 * 
 */
public interface Iterator {
    // 知道是否還有更多元素
    boolean hasNext();

    // 返回下一個元素
    Object next();
}

而後先用DinerMenuIterator類去實現接口測試

package MenuItem;

/**
 * 實現迭代器
 * 
 * @author Joy
 * 
 */
public class DinerMenuIterator implements Iterator {
    MenuItem[] items;
    int position = 0;// 數組索引

    // 構造器初始化傳入一個菜單項的數組當參數
    public DinerMenuIterator(MenuItem[] items) {
        this.items = items;
    }

    // 返回數組下一項,索引自+1
    @Override
    public Object next() {
        MenuItem menuItem = items[position];
        position += 1;
        return menuItem;
    }

    // 判斷數組是否滿了
    @Override
    public boolean hasNext() {
        if (position >= items.length || items[position] == null) {
            return false;
        }
        return true;
    }
}

咱們有了菜單迭代器,利用它改寫餐廳菜單,DineMenu類中這樣寫this

package MenuItem;

/**
 * 對象村餐廳
 * 
 * @author Joy
 * 
 */
public class DineMenu {
    // 菜單總數
    static final int MAX_ITEMS = 6;
    // 菜單量
    int numberOfItems = 0;
    MenuItem[] menuItems;

    // 初始化數組,添加菜單內容
    public DineMenu() {
        menuItems = new MenuItem[MAX_ITEMS];
        addItem("素食BLT", "(煎)培根、生菜&西紅柿並用麪包作", true, 2.99);
        addItem("BLT", "培根、生菜&西紅柿", false, 2.99);
        addItem("例湯", "一碗例湯、配土豆沙拉", false, 3.29);
        addItem("熱狗", "熱狗、酸菜、上蓋芝士", false, 3.29);
        addItem("清蒸時蔬加糙米", "清蒸的蔬菜配糙米", false, 3.05);

    }

    // 建立一個添加菜單方法
    public void addItem(String name, String description, boolean vegetarian,
            double price) {
        MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
        if (numberOfItems >= MAX_ITEMS) {
            System.out.println("抱歉,菜單已滿,不能添加菜單了");
        } else {
            // 菜單還沒滿還能夠繼續添加
            menuItems[numberOfItems] = menuItem;
            numberOfItems += 1;
        }
    }

    // 使用迭代器遍歷菜單
    public Iterator createIterator() {
        return new DinerMenuIterator(menuItems);
    }
}

完整代碼以下
圖片描述spa

迭代器接口設計

package MenuItem;

/**
 * 迭代器接口
 * 
 * @author Joy
 * 
 */
public interface Iterator {
    // 知道是否還有更多元素
    boolean hasNext();

    // 返回下一個元素
    Object next();
}

菜單類code

package MenuItem;

/**
 * 對象村餐廳
 * 
 * @author Joy
 * 
 */
public class DineMenu {
    // 菜單總數
    static final int MAX_ITEMS = 6;
    // 菜單量
    int numberOfItems = 0;
    MenuItem[] menuItems;

    // 初始化數組,添加菜單內容
    public DineMenu() {
        menuItems = new MenuItem[MAX_ITEMS];
        addItem("素食BLT", "(煎)培根、生菜&西紅柿並用麪包作", true, 2.99);
        addItem("BLT", "培根、生菜&西紅柿", false, 2.99);
        addItem("例湯", "一碗例湯、配土豆沙拉", false, 3.29);
        addItem("熱狗", "熱狗、酸菜、上蓋芝士", false, 3.29);
        addItem("清蒸時蔬加糙米", "清蒸的蔬菜配糙米", false, 3.05);

    }

    // 建立一個添加菜單方法
    public void addItem(String name, String description, boolean vegetarian,
            double price) {
        MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
        if (numberOfItems >= MAX_ITEMS) {
            System.out.println("抱歉,菜單已滿,不能添加菜單了");
        } else {
            // 菜單還沒滿還能夠繼續添加
            menuItems[numberOfItems] = menuItem;
            numberOfItems += 1;
        }
    }

    // 使用迭代器遍歷菜單
    public Iterator createIterator() {
        return new DinerMenuIterator(menuItems);
    }
}

餐廳的實現以及接口

package MenuItem;

/**
 * 實現迭代器
 * 
 * @author Joy
 * 
 */
public class DinerMenuIterator implements Iterator {
    MenuItem[] items;
    int position = 0;// 數組索引

    // 構造器初始化傳入一個菜單項的數組當參數
    public DinerMenuIterator(MenuItem[] items) {
        this.items = items;
    }

    // 返回數組下一項,索引自+1
    @Override
    public Object next() {
        MenuItem menuItem = items[position];
        position += 1;
        return menuItem;
    }

    // 判斷數組是否滿了
    @Override
    public boolean hasNext() {
        if (position >= items.length || items[position] == null) {
            return false;
        }
        return true;
    }
}
package MenuItem;

/**
 * 對象村餐廳
 * 
 * @author Joy
 * 
 */
public class DineMenu {
    // 菜單總數
    static final int MAX_ITEMS = 6;
    // 菜單量
    int numberOfItems = 0;
    MenuItem[] menuItems;

    // 初始化數組,添加菜單內容
    public DineMenu() {
        menuItems = new MenuItem[MAX_ITEMS];
        addItem("素食BLT", "(煎)培根、生菜&西紅柿並用麪包作", true, 2.99);
        addItem("BLT", "培根、生菜&西紅柿", false, 2.99);
        addItem("例湯", "一碗例湯、配土豆沙拉", false, 3.29);
        addItem("熱狗", "熱狗、酸菜、上蓋芝士", false, 3.29);
        addItem("清蒸時蔬加糙米", "清蒸的蔬菜配糙米", false, 3.05);

    }

    // 建立一個添加菜單方法
    public void addItem(String name, String description, boolean vegetarian,
            double price) {
        MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
        if (numberOfItems >= MAX_ITEMS) {
            System.out.println("抱歉,菜單已滿,不能添加菜單了");
        } else {
            // 菜單還沒滿還能夠繼續添加
            menuItems[numberOfItems] = menuItem;
            numberOfItems += 1;
        }
    }

    // 使用迭代器遍歷菜單
    public Iterator createIterator() {
        return new DinerMenuIterator(menuItems);
    }
}

同理煎餅屋的實現和接口

package MenuItem;

import java.util.ArrayList;

public class PancakeHouseIterator implements Iterator {
    ArrayList items;
    int position = 0;

    public PancakeHouseIterator(ArrayList items) {
        this.items = items;
    }

    @Override
    public Object next() {
        Object obj = items.get(position);
        position += 1;
        return obj;
    }

    @Override
    public boolean hasNext() {
        if (position >= items.size()) {
            return false;
        }
        return true;
    }
}
package MenuItem;

import java.util.ArrayList;

/**
 * 對象村煎餅屋菜單
 * 
 * @author Joy
 * 
 */
public class PancakeHouseMenu {
    ArrayList menuItems;

    public PancakeHouseMenu() {
        menuItems = new ArrayList();
        addItem("K&B薄煎餅早餐", "薄煎餅,清蛋和吐司", true, 2.99);
        addItem("薄煎餅早餐例餐", "薄煎餅,煎蛋和香腸", false, 2.99);
        addItem("藍莓薄煎餅", "新鮮藍莓和藍莓糖漿作成的薄煎餅", false, 3.49);
        addItem("鬆餅", "能夠選擇藍莓或草莓", true, 3.59);        

    }

    // 建立一個添加菜單方法
    public void addItem(String name, String description, boolean vegetarian,
            double price) {
        // 菜單項對象,並加入到ArrayList裏
        MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
        menuItems.add(menuItem);
    }

    //使用迭代器遍歷菜單
    public Iterator createIterator(){
        return new PancakeHouseIterator(menuItems);
    }
}

女招待的實現

package MenuItem;
/**
 * 對象村的女招待
 * 
 * @author Joy
 * 
 */
public class Waitress {
    //建立兩個餐廳對象的引用
    PancakeHouseMenu pancakeHouseMenu;
    DineMenu dineMenu;

    // 初始化兩個菜單
    public Waitress(PancakeHouseMenu pancakeHouseMenu, DineMenu dineMenu) {
        this.dineMenu = dineMenu;
        this.pancakeHouseMenu = pancakeHouseMenu;
    }

    public void printMenu() {
        // 爲每個菜單建立一個迭代器
        Iterator pancakeitIterator = pancakeHouseMenu.createIterator();
        Iterator dinerIterator = dineMenu.createIterator();
        System.out.println("Menu\n=======\nBreakFast");
        // 調用下面重載的方法
        printMenus(pancakeitIterator);
        System.out.println("\nLunch");
        // 調用下面重載的方法
        printMenus(dinerIterator);
    }

    // 重載一個printMenu()方法
    // 使用迭代器(一次循環便可)來遍歷菜單項並打印出來,只調用Iterator接口
    public void printMenus(Iterator iterator) {
        while (iterator.hasNext()) {
            // 取得下一項
            MenuItem menuItem = (MenuItem) iterator.next();
            System.out.print(menuItem.getName() + ", ");
            System.out.print(menuItem.getPrice() + ", ");
            System.out.println(menuItem.getDescription());
        }
    }
}

測試類

package TestMain;
import MenuItem.DineMenu;
import MenuItem.PancakeHouseMenu;
import MenuItem.Waitress;

public class MenuTestDrive {
    public static void main(String[] args) {
        PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();        
        DineMenu dineMenu = new DineMenu();
        /**
         *兩個菜單都實現同樣的方法,可是並無實現相同的接口,
         *女招待仍是要依賴兩個具體實現的菜單類
         *後面就要修改這裏
         *
         */
        Waitress waitress = new Waitress(pancakeHouseMenu, dineMenu);
        waitress.printMenu();
    }
}

效果圖以下
圖片描述

很巧妙的將二者迭代取出來了。但二者實現的接口卻徹底同樣,這裏其實還能夠抽象出來成一個共同接口。

感謝你看到這裏,迭代器模式上部分到這裏就結束了,本人文筆隨便,如有不足或錯誤之處望給予指點,90度彎腰~~~很快我會補全這個內容,生命不息,編程不止!

參考書籍《Head First設計模式》
相關文章
相關標籤/搜索