日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

軟件設(shè)計(jì)模式修煉 -- 迭代器模式

 行者花雕 2021-07-18

迭代器模式是一種使用頻率非常高的設(shè)計(jì)模式,迭代器用于對(duì)一個(gè)聚合對(duì)象進(jìn)行遍歷。通過(guò)引入迭代器可以將數(shù)據(jù)的遍歷功能從聚合對(duì)象中分離出來(lái),聚合對(duì)象只負(fù)責(zé)存儲(chǔ)數(shù)據(jù),聚合對(duì)象只負(fù)責(zé)存儲(chǔ)數(shù)據(jù),而遍歷數(shù)據(jù)由迭代器來(lái)完成。


模式動(dòng)機(jī)

一個(gè)聚合對(duì)象,如一個(gè)列表(List)或者一個(gè)集合(Set),應(yīng)該提供一種方法來(lái)讓別人可以訪問(wèn)它的元素,而又不需要暴露它的內(nèi)部結(jié)構(gòu)。此外,針對(duì)不同的需要,可能還要以不同方式遍歷整個(gè)聚合對(duì)象,但是我們不希在聚合對(duì)象的抽象層接口中充斥著各種不同遍歷的操作。怎樣遍歷一個(gè)聚合對(duì)象,又不需要了解聚合對(duì)象的內(nèi)部結(jié)構(gòu),還能提供多種不同的遍歷方式,這就是迭代器模式所要解決的問(wèn)題。

迭代器模式中,提供一個(gè)外部的迭代器來(lái)對(duì)聚合對(duì)象進(jìn)行訪問(wèn)和遍歷,迭代器定義一個(gè)訪問(wèn)該聚合元素的接口,并且可以跟蹤當(dāng)前遍歷對(duì)象,了解哪些元素已經(jīng)遍歷過(guò)而哪些沒(méi)有。


模式定義

提供一種方法來(lái)訪問(wèn)聚合對(duì)象,而不用暴露這個(gè)對(duì)象的內(nèi)部表示,其別名為游標(biāo)(Cursor)。迭代器模式是一種對(duì)象行為模式。


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

  1. Iterator(抽象迭代器)

    抽象迭代器定義了訪問(wèn)和遍歷元素的接口,一般聲明以下方法:

    • 用于獲取第一個(gè)元素的 first()
    • 用于訪問(wèn)下一個(gè)元素的 next()
    • 用于判斷是否還有下一個(gè)元素的 hasNext()
    • 用于獲取當(dāng)前元素的 currentItem()
  2. ConcreteIterator(具體迭代器)

    具體迭代器實(shí)現(xiàn)了抽象迭代器接口,完成對(duì)聚合對(duì)象的遍歷,同時(shí)在對(duì)聚合進(jìn)行遍歷時(shí)跟蹤其當(dāng)前位置

  3. Aggregate(抽象聚合類)

    抽象聚合類用于存儲(chǔ)對(duì)象,并定義創(chuàng)建相應(yīng)迭代器對(duì)象的接口,聲明一個(gè) createIterator() 方法用于創(chuàng)建一個(gè)迭代器對(duì)象

  4. ConcreteAggregate(具體聚合類)

    具體聚合類實(shí)現(xiàn)了創(chuàng)建相應(yīng)迭代器的接口,實(shí)現(xiàn)了在聚合類中聲明的 createIterator() 方法,該方法返回一個(gè)與具體聚合對(duì)應(yīng)的具體迭代器 ConcreteIterator 實(shí)例


模式分析

存儲(chǔ)數(shù)據(jù)是聚合對(duì)象的最基本職責(zé),其中包含存儲(chǔ)數(shù)據(jù)的類型、存儲(chǔ)空間的大小、存儲(chǔ)空間的分配,以及存儲(chǔ)的方式和順序。然而,聚合對(duì)象除了能存儲(chǔ)數(shù)據(jù)外,還必須提供遍歷訪問(wèn)其內(nèi)部數(shù)據(jù)的方式,同時(shí)這些遍歷方式可能會(huì)根據(jù)不同的情形提供不同的實(shí)現(xiàn)。

因此,聚合對(duì)象主要有兩個(gè)職責(zé):一是存儲(chǔ)內(nèi)部數(shù)據(jù);二是遍歷內(nèi)部數(shù)據(jù)。前者是聚合對(duì)象的基本功能,后者是可以分離的。根據(jù)單一職責(zé)原則,對(duì)象承擔(dān)的職責(zé)越少,對(duì)象的穩(wěn)定性就越好,我們將遍歷聚合對(duì)象中數(shù)據(jù)的行為提取出來(lái),封裝到一個(gè)迭代器中,通過(guò)專門的迭代器來(lái)遍歷聚合對(duì)象的內(nèi)部數(shù)據(jù)。迭代器模式是單一職責(zé)原則的完美體現(xiàn)。

下面通過(guò)一個(gè)簡(jiǎn)單的自定義迭代器來(lái)分析迭代器模式的結(jié)構(gòu)

首先定義一個(gè)簡(jiǎn)單的迭代器去接口

public interface MyIterator {
    void first();// 訪問(wèn)第一個(gè)元素
    void next();// 訪問(wèn)下一個(gè)元素
    boolean isLast();// 判斷是否是最后一個(gè)元素
    Object currentItem();// 獲取當(dāng)前元素
}

然后需要定義一個(gè)聚合接口

public interface MyCollection {
    // 返回一個(gè) MyIterator 迭代器對(duì)象
    MyIterator createIterator();
}

定義好抽象層之后,我們需要定義抽象迭代器接口和抽象聚合接口的實(shí)現(xiàn)類,一般將具體迭代器類作為具體聚合類的內(nèi)部類,從而迭代器可以實(shí)現(xiàn)直接訪問(wèn)聚合類中的數(shù)據(jù)

public class NewCollection implements MyCollection {
    
    private Object[] obj = {"dog", "pig", "cat", "monkey", "pig"};
    
    public MyIterator createIterator() {
        return new NewIterator();
    }
    
    private class NewIterator implements MyIterator {
        
        private int currentIndex = 0;
        
        public void first() {
            currentIndex = 0;
        }
        
        public void next() {
            if(currentIndex < obj.length) {
                currentIndex++;
            }
        }
        
        public boolean isLast() {
            return currentIndex == obj.length;
        }
        
        public void currentItem() {
            return obj[currentIndex];
        }
    }     
}

NewCollection 類實(shí)現(xiàn)了 MyCollection 接口,實(shí)現(xiàn)了 createIterator() 方法,同時(shí)定義了一個(gè)數(shù)組用于存儲(chǔ)數(shù)據(jù)元素,還定義了一個(gè)實(shí)現(xiàn)了 MyIterator 接口的內(nèi)部類,索引變量 currentIndex 用于保存所操作的數(shù)組元素的下標(biāo)值??蛻舳舜a如下:

public class Client {
    
    public static void process(MyCollection collection) {
        MyIterator i = collection.createIterator();
        while(!i.isLast()) {
            System.out.println(i.currentItem().toString());
            i.next();
        }
    }
    
    public static void main(String args[]) {
        MyCollection collection = new NewCollection();
        process(collection);
    }
}

除了使用內(nèi)部類實(shí)現(xiàn)之外,也可以使用常規(guī)的方式來(lái)實(shí)現(xiàn)迭代器

public class ConcreteIterator implements Iterator {
    
    private ConcreteAggregate objects;
    
    public ConcreteIterator(ConcreteAggregate objects) {
        this.objects = objects;
    }
    
    public void first() {
        ...
    }
        
    public void next() {
        ...
    }
        
    public boolean isLast() {
        ...
    }
        
    public void currentItem() {
        ...
    }
}

public class ConcreteAggregate implements Aggregate {
    ...
    public Iterator createIterator() {
        return new ConcreteIterator(this);
    }
}

迭代器模式中應(yīng)用了工廠方法模式,聚合類充當(dāng)工廠類,而迭代器充當(dāng)產(chǎn)品類


模式優(yōu)缺點(diǎn)

迭代器模式優(yōu)點(diǎn):

  1. 支持以不同的方式遍歷一個(gè)聚合對(duì)象。在迭代器模式中只需要用一個(gè)不同的迭代器來(lái)替換原有迭代器即可改變遍歷算法,也可以自己定義迭代器的子類以支持新的遍歷方式。
  2. 迭代器簡(jiǎn)化了聚合類。原有聚合對(duì)象不再需要自行提供遍歷數(shù)據(jù)等操作方法。
  3. 在同一個(gè)聚合上可以有多個(gè)遍歷。由于每個(gè)迭代器都保持自己的遍歷狀態(tài),因此可以對(duì)一個(gè)聚合對(duì)象進(jìn)行多個(gè)遍歷操作。
  4. 增加新的聚合類和迭代器類都很方便,無(wú)須修改原代碼,滿足開閉原則。

迭代器模式缺點(diǎn):

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

模式適用環(huán)境

在以下情況可以使用迭代器模式:

  1. 訪問(wèn)一個(gè)聚合對(duì)象的內(nèi)容而無(wú)須暴露它的內(nèi)部表示
  2. 需要為聚合對(duì)象提供多種遍歷方式
  3. 為遍歷不同的聚合結(jié)構(gòu)提供一個(gè)統(tǒng)一的接口

Java 迭代器

Java 中的集合框架 Collections,其基本接口層次結(jié)構(gòu)如圖

Collection 是所有集合類的根接口,它的主要方法如下:

boolean add(Object c);
boolean addAll(Collection c);
boolean remove(Object o);
boolean removeAll(Collection c);
boolean remainAll(Collection c);
Iterator iterator();

Collection 的 iterator() 方法返回一個(gè) java.util.Iterator 類型的對(duì)象,而其子接口 java.util.List 的 listIterator() 方法返回一個(gè) java.util.ListIterator 類型的對(duì)象,ListIterator 是 Iterator 的子類,它們構(gòu)成了 Java 語(yǔ)言對(duì)迭代器模式的支持。

在 JDK 中,Iterator 接口具有如下三個(gè)基本方法:

  1. Object next():通過(guò)反復(fù)調(diào)用 next() 方法可以逐個(gè)訪問(wèn)聚合中的元素
  2. boolean hasNext():用于判斷聚合對(duì)象在是否還存在下一個(gè)元素,為了不拋出異常,必須在調(diào)用 next() 之前先調(diào)用 hasNext()。如果迭代對(duì)象仍然擁有可供訪問(wèn)的元素,那么 hasNext() 返回 true
  3. void remove():刪除上一次調(diào)用 next() 時(shí)返回的元素

Java 迭代器可以理解為它工作時(shí)在聚合對(duì)象的各個(gè)元素之間,每調(diào)用一次 next() 方法,迭代器便越過(guò)下個(gè)元素,并且返回它剛越過(guò)的那個(gè)元素的地址引用。

在第一個(gè) next() 方法被調(diào)用時(shí),迭代器由“元素1”與“元素2”之間移動(dòng)至“元素2”與“元素3”之間,跨越了“元素2”,因此 next() 方法將返回對(duì)“元素2”的引用;在第二個(gè) next() 方法被調(diào)用時(shí),迭代器由“元素2”與“元素3”之間移至“元素3”與“元素4”之間,next() 方法將返回對(duì)“元素3”的引用,此時(shí)調(diào)用 remove() 方法,則可將”元素3“刪除。

需要注意的是,next() 方法與 remove() 方法的調(diào)用是相互關(guān)聯(lián)的。如果調(diào)用 remove() 之前沒(méi)有先對(duì) next() 進(jìn)行調(diào)用,那么將拋出異常,因?yàn)闆](méi)有任何可供刪除的元素


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多