設計模式(十六)迭代器模式 Iterator

  • 何時須要用到迭代器模式?

  有許多中方法,能夠把對象堆起來放進一個集合(能夠是數組、堆棧、列表、哈希表,等等)。數組

  每一種類型的集合,都有各自適用的時機。可是某個時間段,客戶端可能但願去遍歷這個集合。數據結構

  怎麼作?ide

  讓客戶去獲得這個集合的具體實現?顯然這不是很現實。ui

  並且針對不一樣的集合,咱們須要用不一樣的方式去遍歷它,這須要去深刻了解各類數據結構,對客戶端很不友好。spa

 

  這時候,咱們但願建立一種超集合(super collection),是客戶端可以使用統一的方法去遍歷集合,同時不須要關心具體的數據結構。code

  這就是迭代器模式。對象

 

  • 迭代器模式:

  迭代器模式提供一種方法,順序訪問一個聚合對象中的各個元素,而又不暴露其內部的表示。blog

  從 Java 的角度來講,迭代器模式就是 Iterator 接口。接口

 

  • 模擬場景:

  有一個水果商店(FruitShop),內部採起數組的方式存儲數據。get

  有一個肉食商店(MeatShop),內部採用鏈表的方式存儲數據。

  客戶端但願去遍歷這些數據,

 

  • 沒有迭代器的實現:
public final class FruitShop {

    private String[] products = new String[MAX_PRODUCT];
    private int index = 0;

    private static final int MAX_PRODUCT = 10;

    public void addProduct(String product) {
        if (index < MAX_PRODUCT) {
            products[index++] = product;
        } else {
            throw new RuntimeException("FruitShop is full");
        }
    }

    public String[] getProducts() {
        return Arrays.copyOf(products, index);
    }
}
public final class MeatShop {

    private List<String> products = new LinkedList<>();

    public void addProduct(String product) {
        products.add(product);
    }

    public List<String> getProducts() {
        return products;
    }
}
    @Test
    void testFruitShop() {
        FruitShop fruitShop = new FruitShop();
        fruitShop.addProduct("Apple");
        fruitShop.addProduct("Orange");
        String[] products = fruitShop.getProducts();
        for (String product : products) {
            System.out.println(product);
        }
    }

    @Test
    void testMeatShop() {
        MeatShop meatShop = new MeatShop();
        meatShop.addProduct("Beef");
        meatShop.addProduct("Pork");
        List<String> products = meatShop.getProducts();
        for (String product : products) {
            System.out.println(product);
        }
    }

 

  上面的代碼有以下的問題:

  1. 兩個 Shop 暴露了內部的數據結構。
  2. 客戶端採起不一樣的方法去遍歷數據。

 

  • 包含迭代器的實現
public final class FruitShopIterator implements Iterator<String> {

    private String[] products = new String[MAX_PRODUCT];
    private int index = 0;

    private int iteratorIndex = 0;

    private static final int MAX_PRODUCT = 10;

    public void addProduct(String product) {
        if (index < MAX_PRODUCT) {
            products[index++] = product;
        } else {
            throw new RuntimeException("FruitShop is full");
        }
    }

    @Override
    public boolean hasNext() {
        return iteratorIndex < index;
    }

    @Override
    public String next() {
        return products[iteratorIndex++];
    }
}
public final class MeatShopIterator implements Iterator<String> {

    private List<String> products = new LinkedList<>();
    private int iteratorIndex = 0;

    public void addProduct(String product) {
        products.add(product);
    }

    @Override
    public boolean hasNext() {
        return iteratorIndex < products.size();
    }

    @Override
    public String next() {
        return products.get(iteratorIndex++);
    }
}
    @Test
    void testFruitShopIterator() {
        FruitShopIterator fruitShop = new FruitShopIterator();
        fruitShop.addProduct("Apple");
        fruitShop.addProduct("Orange");
        while (fruitShop.hasNext()) {
            System.out.println(fruitShop.next());
        }
    }

    @Test
    void testMeatShopIterator() {
        MeatShopIterator meatShop = new MeatShopIterator();
        meatShop.addProduct("Beef");
        meatShop.addProduct("Pork");
        while (meatShop.hasNext()) {
            System.out.println(meatShop.next());
        }
    }

 

  能夠看出:

  1. Iterator 提供了 hasNext() 和 next() 方法負責集合數據的遍歷。
  2. Shop 類避免了暴露具體的數據結構。
  3. 客戶端採用統一的方式去遍歷數據。
相關文章
相關標籤/搜索