設計模式(十)幾段代碼搞懂迭代器模式

關於迭代器模式的定義,我就直接引用Head First了:迭代器模式提供一種方法順序訪問一個聚合對象中的各個元素,而又不暴露其內部的表示。這裏的聚合就是我們常說的集合,迭代器模式能讓我們遍歷集合內的對象,而又無需暴露集合本身的存儲結構(如數組,鏈表,散列表等),把遍歷的任務封裝起來,放在迭代器對象上,使其與集合所在的對象解耦。那爲何要將遍歷的部分封裝起來?其目的是爲了讓類的職責變得單一,讓集合能更專注於自身職責的處理。具體看下:

迭代器模式

假如廠商有兩款智能設備產品,爲:智能音箱和智能空調,現廠商決定要打造智能生態系統,需要將兩款智能設備的用戶整合到一起。但由於兩個部門對於數據處理模塊都有着各自的考量,所以讓本次的合併困難重重(一個是List,一個是數組,兩者的接口方法不一致)

這是當前的智能音箱類

public class SpeakerBox {
    ArrayList<User> users = new ArrayList();

    public void register(User user) {
        users.add(user);
    }
    public ArrayList getUsers() {
        return users;
    }
    /**
     * 當然內部還有很多複雜的邏輯處理,
     * 都依賴於此ArrayList容器,
     * 導致無法輕易更改存儲結構。
     */
}

這是當前的智能空調類

public class AirConditioner {
    static final int MAX_USER_COUNT = 100;
    User[] users = new User[MAX_USER_COUNT];
    int curItemCount = 0;

    public void register(User user) {
        if (curItemCount >= MAX_USER_COUNT)
            System.out.println("用戶超額!");
        else {
            users[curItemCount] = user;
            curItemCount++;
        }
    }
    public User[] getUsers() {
        return users;
    }
}

這是用戶信息類

public class User {
    private String ID;
    public String getId() {
        return ID;
    }
}

兩部門老大經過一番商談,最後決定將用戶集合的迭代工作從各自的數據處理模塊中抽離出來,讓處理模塊的職責更單一些,以達到降低耦合的目的。個人認爲此處所說的“迭代” 只是迭代器模式的標準形式,其實不僅僅是迭代,我們還能抽離出很多其他的操作,如插首、插尾,甚至自定義的操作等。我覺得它的意圖是給不同結構的集合,通過迭代器類,抽離出一套對外的統一的接口供用戶使用,讓用戶無需關心所處理的集合的結構表示,只需要針對Iterator 編程就可以

這是兩部門抽離出的迭代器接口類(當然也可以使用Java 自帶的java.util.Iterator 適配器接口,這裏就直接使用自定義的了)。

public interface Iterator {
    boolean hasNext();
    Object next();
}

這是智能音箱部門實現的音箱適配器類

public class SpeakerBoxIterator implements Iterator {
    ArrayList<User> users;
    int curItemCount = 0;
    int size;
    public SpeakerBoxIterator(ArrayList<User> users) {
        this.users = users;
        if (null != this.users)
            size = this.users.size;
    }
    @Override public boolean hasNext() {
        return curItemCount < size;
    }
    @Override public Object next() {
        if (curItemCount >= size)
            return null;
        else {
            int cursor = curItemCount;
            curItemCount++;
            return users.get(cursor);
        }
    }
}

同理,這是智能空調部門實現的空調適配器類

public class AirConditionerIterator implements Iterator {
    User[] users;
    int curItemCount = 0;
    int length;
    public AirConditionerIterator(User[] users) {
        this.users = users;
        if (null != this.users)
            length = this.users.length;
    }
    @Override public boolean hasNext() {
        return curItemCount < length;
    }
    @Override public Object next() {
        if (curItemCount >= length)
            return null;
        else {
            int cursor = curItemCount;
            curItemCount++;
            return users[cursor];
        }
    }
}

有了適配器類之後,我們再改造下我們的智能音箱類2.0,能夠看出,我們已經將迭代的責任移交給了 SpeakerBoxIterator 來處理,所以SpeakerBox 本身不需要再提供具體的迭代方法,也不需要對用戶暴露自身的集合類型。

public class SpeakerBox {
    ArrayList<User> users = new ArrayList();

    public void register(User user) {
        users.add(user);
    }
    public Iterator creatIterator() {
        return new SpeakerBoxIterator(users);
    }
}

這是智能空調類2.0

public class AirConditioner {
    static final int MAX_USER_COUNT = 100;
    User[] users = new User[MAX_USER_COUNT];
    int curItemCount = 0;

    public void register(User user) {
        if (curItemCount >= MAX_USER_COUNT)
            System.out.println("用戶超額!");
        else {
            users[curItemCount] = user;
            curItemCount++;
        }
    }
    public Iterator creatIterator() {
        return new AirConditionerIterator(users);
    }
}

這是我們的使用類,能夠發現ClientTest 並不需要知道音箱和空調類內部集合的類型,只需要針對Iterator 編程即可,通過creatIterator 方法就能夠遍歷集合內的每個元素。

public class ClientTest {
    public static void main(String[] ags) {
        // 將智能音箱和空調的用戶打印出來
        Iterator sbIterator = speakerBox.creatIterator();
        Iterator acIterator = airConditioner.creatIterator();
        printInfo(sbIterator);
        printInfo(acIterator);
    }
    private static void printInfo(Iterator iterator) {
        while (iterator.hasNext()) {
            User user = (User) iterator.next();
            System.out.println("用戶ID: " + User.getId());
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章