成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

一起學(xué)設(shè)計(jì)模式 - 迭代器模式

JasonZhang / 3149人閱讀

摘要:迭代器模式屬于行為型模式的一種,提供一種方法訪問一個容器中各個元素,而又不需要暴露該對象的內(nèi)部細(xì)節(jié)。迭代器模式把在元素之間游走的責(zé)任交給迭代器,而不是聚合對象。

迭代器模式(Iterator Pattern)屬于行為型模式的一種,提供一種方法訪問一個容器中各個元素,而又不需要暴露該對象的內(nèi)部細(xì)節(jié)。

概述

迭代器模式聽起來可能感覺很陌生,但是實(shí)際上,迭代器模式是所有設(shè)計(jì)模式中最簡單也是最常用的設(shè)計(jì)模式,正是因?yàn)樘S昧耍詫?dǎo)致很多人忽略了它的存在。

在實(shí)際的開發(fā)過程中,我們可能需要針對不同的需求,可能需要以不同的方式來遍歷整個整合對象,但又不希望在聚合對象的抽象接口層中充斥著各種不同的便利操作。這個時候我們就需要這樣一種東西,它應(yīng)該具備如下三個功能:

能夠便利一個聚合對象。

我們不需要了解聚合對象的內(nèi)部結(jié)構(gòu)。

能夠提供多種不同的遍歷方式。

迭代器模式: 把在元素之間游走的責(zé)任交給迭代器,而不是聚合對象。簡化了聚合的接口和實(shí)現(xiàn),讓聚合更專注在它所應(yīng)該專注的事情上,這樣做更加符合單一責(zé)任原則。

UML結(jié)構(gòu)圖

模式結(jié)構(gòu)

Iterator(抽象迭代器): 具體迭代器需要實(shí)現(xiàn)的接口,提供了游走聚合對象元素之間的方法

ConcreteIterator(具體迭代器): 對具體的聚合對象進(jìn)行遍歷,每一個聚合對象都應(yīng)該對應(yīng)一個具體的迭代器。

Aggregate(抽象聚合類): 存儲和管理元素對象,聲明了createIterator()用于創(chuàng)建一個迭代器對象,充當(dāng)抽象迭代器工廠角色

ConcreteAggregate(具體聚合類): 實(shí)現(xiàn)了在抽象聚合類中聲明的createIterator(),該方法返回一個與該具體聚合類對應(yīng)的具體迭代器ConcreteIterator實(shí)例。

案例

UML圖如下:

1.先定義抽象迭代器``

interface Iterator {

    //判斷是否有還有下一個元素
    boolean hasNext();

    //取出下一個對象
    E next();
}

2.在定義一個具體迭代器對象,實(shí)現(xiàn)了Iterator中的方法

class MusicIterator implements Iterator {

    private E[] es;
    private int position = 0;

    public MusicIterator(E[] es) {
        this.es = es;
    }

    @Override
    public boolean hasNext() {
        return position != es.length;
    }

    @Override
    public E next() {
        E e = es[position];
        position += 1;
        return e;
    }
}

3.接下來定義抽象聚合類(常為 Collection , List , Set 等)

interface AbstractList {

    void add(E e);

    Iterator createIterator();
}

4.最后創(chuàng)建具體聚合類 (常為 ArrayList , HashSet 等,是抽象聚合類的實(shí)現(xiàn)類)

class MusicList implements AbstractList {

    private String[] books = new String[5];
    private int position = 0;


    @Override
    public void add(String name) {
        books[position] = name;
        position += 1;
    }

    @Override
    public Iterator createIterator() {
        return new MusicIterator<>(books);
    }
}

5.創(chuàng)建測試工程

public class Client {

    public static void main(String[] args) {
        AbstractList list = new MusicList();
        list.add("涼涼");
        list.add("奇談");
        list.add("紅顏");
        list.add("伴虎");
        list.add("在人間");
        Iterator iterator = list.createIterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

}

6.運(yùn)行效果

涼涼
奇談
紅顏
伴虎
在人間

至此一個簡單的迭代器就完成了,實(shí)現(xiàn)了對容器的遍歷。可以看到迭代器在Client中遍歷時根本不需要知道他底層的實(shí)現(xiàn),只需要通過迭代器來遍歷就可以了。

JDK中應(yīng)用

上文介紹了自己實(shí)現(xiàn)一個簡單的迭代器,看完的應(yīng)該就不陌生了,它其實(shí)在JAVA的很多集合類中被廣泛應(yīng)用,接下來看看JAVA源碼中是如何使用迭代器模式的。

List list = new ArrayList<>();
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

看完這段代碼是不是很熟悉,與我們上文代碼基本類似

List:抽象聚合器

ArrayList:具體的聚合類

Iterator:抽象迭代器

list.iterator():返回的是實(shí)現(xiàn)了Iterator接口的具體迭代器對象

接下來看下ArrayList中的iterator是如何實(shí)現(xiàn)的

public Iterator iterator() {
    return new Itr();
}

private class Itr implements Iterator {
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;

    public boolean hasNext() {
        return cursor != size;
    }

    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }

    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void forEachRemaining(Consumer consumer) {
        Objects.requireNonNull(consumer);
        final int size = ArrayList.this.size;
        int i = cursor;
        if (i >= size) {
            return;
        }
        final Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length) {
            throw new ConcurrentModificationException();
        }
        while (i != size && modCount == expectedModCount) {
            consumer.accept((E) elementData[i++]);
        }
        // update once at end of iteration to reduce heap write traffic
        cursor = i;
        lastRet = i - 1;
        checkForComodification();
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

這部分代碼還是比較簡單,大致就是在iterator方法中返回了一個實(shí)例化的Iterator對象。Itr是一個內(nèi)部類,它實(shí)現(xiàn)了Iterator接口并實(shí)現(xiàn)了其中的方法。

當(dāng)我們在使用JAVA開發(fā)的時候,想使用迭代器模式的話,只要讓我們自己定義的容器類實(shí)現(xiàn)java.util.Iterable并實(shí)現(xiàn)其中的iterator方法使其返回一個java.util.Iterator的實(shí)現(xiàn)類就可以了。

總結(jié)

迭代器模式與集合共生共死的,一般來說,我們只要實(shí)現(xiàn)一個集合,就需要同時提供這個集合的迭代器,就像java中的Collection,List、Set、Map等,這些集合都有自己的迭代器。假如我們要實(shí)現(xiàn)一個這樣的新的容器,當(dāng)然也需要引入迭代器模式,給我們的容器實(shí)現(xiàn)一個迭代器。但在絕大多數(shù)情況,我們是不需要自己實(shí)現(xiàn)的,基本都內(nèi)置了

優(yōu)點(diǎn)

支持不同方式遍歷一個聚合對象,在同一個聚合上可以有多個遍歷。

簡化了聚合類。由于引入了迭代器,在原有的聚合對象中不需要再自行提供數(shù)據(jù)遍歷等方法。

在迭代器模式中,由于引入了抽象層,增加新的聚合類和迭代器類都很方便,無須修改原有代碼

缺點(diǎn)

由于迭代器模式將存儲數(shù)據(jù)和遍歷數(shù)據(jù)的職責(zé)分離,增加新的聚合類需要對應(yīng)增加新的迭代器類,類的個數(shù)成對增加,這在一定程度上增加了系統(tǒng)的復(fù)雜性。

抽象迭代器的設(shè)計(jì)難度較大,需要充分考慮到系統(tǒng)將來的擴(kuò)展,例如JDK內(nèi)置迭代器Iterator就無法實(shí)現(xiàn)逆向遍歷,如果需要實(shí)現(xiàn)逆向遍歷,只能通過其子類ListIterator等來實(shí)現(xiàn),而ListIterator迭代器無法用于操作Set類型的聚合對象。在自定義迭代器時,創(chuàng)建一個考慮全面的抽象迭代器并不是件很容易的事情。

說點(diǎn)什么

全文代碼:https://gitee.com/battcn/design-pattern/tree/master/Chapter14/battcn-iterator

個人QQ:1837307557

battcn開源群(適合新手):391619659

微信公眾號:battcn(歡迎調(diào)戲)

福利

關(guān)注公眾號:battcn,回復(fù)springboot即可獲得 <2017最新spring boot 外賣實(shí)戰(zhàn)微信公眾平臺視頻教程>

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/70670.html

相關(guān)文章

  • 一起學(xué)設(shè)計(jì)模式 - 備忘錄模式

    摘要:備忘錄模式常常與命令模式和迭代子模式一同使用。自述歷史所謂自述歷史模式實(shí)際上就是備忘錄模式的一個變種。在備忘錄模式中,發(fā)起人角色負(fù)責(zé)人角色和備忘錄角色都是獨(dú)立的角色。 備忘錄模式(Memento Pattern)屬于行為型模式的一種,在不破壞封裝特性的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài)。這樣就可以將該對象恢復(fù)到原先保存的狀態(tài)。 概述 備忘錄模式又叫做快照模式(...

    roland_reed 評論0 收藏0
  • 迭代模式

    摘要:迭代器模式的結(jié)構(gòu)抽象容器一般是一個接口,提供一個方法,例如中的接口,接口,接口等。假如我們要實(shí)現(xiàn)一個這樣的新的容器,當(dāng)然也需要引入迭代器模式,給我們的容器實(shí)現(xiàn)一個迭代器。 定義:提供一種方法訪問一個容器對象中各個元素,而又不暴露該對象的內(nèi)部細(xì)節(jié)。 類型:行為類模式。 類圖:showImg(https://segmentfault.com/img/bVWQIQ?w=542&h=287);...

    xcc3641 評論0 收藏0
  • 練就Java24章真經(jīng)—你所不知道的工廠方法

    摘要:用專業(yè)的話來講設(shè)計(jì)模式是一套被反復(fù)使用多數(shù)人知曉的經(jīng)過分類編目的代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)創(chuàng)建型模式,共五種工廠方法模式抽象工廠模式單例模式建造者模式原型模式。工廠方法模式的擴(kuò)展性非常優(yōu)秀。工廠方法模式是典型的解耦框架。 前言 最近一直在Java方向奮斗《終于,我還是下決心學(xué)Java后臺了》,今天抽空開始學(xué)習(xí)Java的設(shè)計(jì)模式了。計(jì)劃有時間就去學(xué)習(xí),你這么有時間,還不來一起上車嗎? 之所以要學(xué)...

    Chiclaim 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<