Definition: Bietet eine Methode zum Zugriff auf verschiedene Elemente in einem Containerobjekt, ohne die internen Details des Objekts freizulegen.
Typ: Verhaltensmuster
Klassendiagramm:
Wenn Sie den am häufigsten verwendeten Modus in Java fragen möchten, ist die Antwort weder der Singleton -Modus noch der Werksmodus, noch der Strategiemodus, sondern der Iteratormodus. Schauen wir uns zuerst einen Code an:
public static void print (Sammlung coll) {iterator it = coll.iterator (); while (it.hasnext ()) {String str = (string) it.next (); System.out.println (str); }} Die Funktion dieser Methode besteht darin, eine String -Sammlungsschleife zu drucken, und das Iteratormuster wird im Iteratormuster verwendet. Die Java -Sprache hat das Iteratormuster vollständig implementiert. Iterator, das in Chinese übersetzt wird, bedeutet Iterator. Wenn es um Iteratoren geht, hängt es zunächst mit Sets zusammen. Sets werden auch Aggregate, Container usw. bezeichnet. Wir können Sätze als Container betrachten, die Objekte enthalten können. Beispielsweise können List, Set, Map und sogar Arrays als Sets bezeichnet werden. Die Funktion der Iteratoren besteht darin, die Objekte im Container einzeln zu durchqueren.
Die Struktur des Iteratormusters
Abstract Container: Im Allgemeinen wird die Iterator () -Methode bereitgestellt, z. B. die Sammlungsschnittstelle, Listenschnittstelle, Set -Schnittstelle usw. in Java.
Spezifischer Container: Es ist die konkrete Implementierungsklasse abstrakter Container, wie die geordnete Liste der Listenschnittstelle zu implementieren ArrayList, die verknüpfte Liste der List -Schnittstelle zum Implementieren von LinkList, die Hash -Liste der festgelegten Schnittstelle zum Implementieren von Hashset usw.
Abstract Iterator: Definieren Sie die Methode, die zum Durchqueren von Elementen erforderlich ist. Im Allgemeinen gibt es drei Methoden: Erhalten Sie die erste () -Methode des ersten Elements, erhalten Sie die nächste () Methode des nächsten Elements, bestimmen Sie, ob die Methode des Durchquerens isdone () (oder hasNext ()), remove () des aktuellen Objekts beendet.
Iterator -Implementierung: Implementiert die in der Iterator -Schnittstelle definierten Methoden, um die Iteration der Sammlung zu vervollständigen.
Geben Sie ein Beispiel an
Da die Vorschriften des Iteratormodus selbst relativ locker sind, ist die spezifische Implementierung vielfältig. Lassen Sie uns hier nur ein Beispiel geben, und wir können die Implementierungsmethoden nacheinander nicht vorstellen. Lassen Sie uns daher vor einem Beispiel die Implementierungsmethoden des nächsten Iteratormusters auflisten.
1. Die Iteratorrolle definiert die Schnittstelle für den Durchqueren, gibt jedoch nicht an, wer die Iteration steuert. Bei der Anwendung der Java -Sammlung wird der Prozess des Traversals vom Client -Programm gesteuert, das als externer Iterator bezeichnet wird. Eine andere Implementierungsmethode besteht darin, den Iterator selbst zu steuern, der als interner Iterator bezeichnet wird. Externe Iteratoren sind flexibel und leistungsfähig als interne Iteratoren, und interne Iteratoren sind in der Java -Gebietsschemasumgebung sehr schwach.
2. Es gibt keine Bestimmung dafür, wer den Traversalalgorithmus im Iteratormodus implementiert. Es scheint selbstverständlich zu sein, in der Iteratorrolle umzusetzen. Da es für verschiedene Traversalalgorithmen in einem Behälter bequem ist, ist es auch bequem, einen Traversalalgorithmus auf verschiedene Behälter anzuwenden. Dies zerstört jedoch die Verkapselung des Containers - die Containerrolle muss ihre eigenen privaten Attribute offenlegen, was in Java bedeutet, ihre eigenen privaten Attribute anderen Klassen auszusetzen.
Dann legen wir es in die Containerrolle, um es zu implementieren. Auf diese Weise wird die Iteratorrolle außer Kraft gesetzt, um nur eine Funktion zu speichern, die den aktuellen Standort durchquert. Der Traversalalgorithmus ist jedoch fest an einen bestimmten Behälter gebunden.
Bei der Anwendung der Java -Sammlung ist die spezifische Iteratorrolle die interne Klasse, die in der Containerrolle definiert ist. Dies schützt die Verpackung des Behälters. Gleichzeitig bietet der Container auch eine Schnittstelle für Traversalalgorithmus, und Sie können Ihren eigenen Iterator erweitern.
Ok, schauen wir uns an, wie der Iterator in der Java -Sammlung implementiert wird.
// Iteratorrolle definiert nur die öffentliche Schnittstelle von Traversal Interface Iterator {boolean hasNext (); Objekt Next (); void remove ();} // Containerrolle, nimm die Liste hier als Beispiel. Es ist nur eine Schnittstelle, daher wird es nicht aufgeführt. Die spezifische Containerrolle ist ArrayList und andere Klassen, die die Listenschnittstelle implementieren. Um die wichtigsten Punkte hervorzuheben, beziehen wir uns auf den Inhalt des Iterators // Die spezifische Iteratorrolle wird in Form einer internen Klasse abgeleitet. Die Abstractlist gibt es, um die gemeinsamen Teile jeder spezifischen Behälterrolle zu extrahieren. public abstract class AbstractList erweitert die AbstractCollection implementiert die Liste {... // Dies ist die Werksmethode, die für die Erstellung spezifischer Iteratorrollen public iterator () {neue ITR () zurückgeben;} // als spezifische Iteratorrolle der internen Klasse Iterator Iterator {int Cursor = 0; int lastret = -1; int erwartModcount = modcount; public boolean hasNext () {return cursor! = size (); } public Object next () {techeforComodification (); Versuchen Sie {Object next = get (cursor); Lastret = Cursor ++; Als nächstes zurückkehren; } catch (indexoutOfBoundSexception e) {checkforComodification (); neue NoSuchelementException () werfen; }} public void remove () {if (lastret == -1) werfen neue illegaleStateException (); checkforComodification (); try {AbstractList.this.Remove (Lastret); if (lastret <cursor) cursor--; Lastret = -1; erweitertModcount = modcount; } catch (indexoutOfboundSexception e) {neue ConcurrentModificationException (); }} endgültig void checkforComodification () {if (modcount! = erwartungsModcount) werfen neue ConcurrentModificationException (); }}Wie für die Verwendung des Iteratormodus. Wie in der Einführung aufgeführt, muss das Client -Programm zuerst die spezifische Containerrolle und dann die spezifische Iteratorrolle durch die spezifische Containerrolle einholen. Auf diese Weise können Sie die spezifische Iteratorrolle verwenden, um den Behälter zu durchqueren ...
Vor- und Nachteile des Iteratormodus
Die Vorteile des Iteratormodus sind:
Die Traversalmethode wurde vereinfacht und es ist immer noch ziemlich problematisch, die Objektsammlung zu durchqueren. Für Arrays oder geordnete Listen können wir sie dennoch über Cursors erhalten, aber Benutzer müssen die Objekte selbst über die Prämisse durchqueren, dass sie ein klares Verständnis der Sammlung haben. Für die Hash -Tabelle ist es jedoch schwieriger, den Benutzer zu durchqueren. Nach der Einführung der Iterator -Methode ist es für Benutzer viel einfacher zu verwenden.
Es gibt viele Möglichkeiten, um zu überqueren, beispielsweise für geordnete Listen können wir zwei Iteratoren mit positiver Reihenfolge und Umkehrreihenfolge nach Bedarf zur Verfügung stellen. Benutzer müssen nur den Iterator erhalten, den wir implementiert haben, um die Sammlung einfach zu durchqueren.
Die Einkapselung ist gut und Benutzer müssen nur einen Iterator zum Durchlaufen bringen, aber sie müssen sich keine Sorgen um Traversalalgorithmen machen.
Nachteile des Iteratormusters:
Für einfache Traverals (wie Arrays oder bestellte Listen) ist es mehr umständlich, Iteratoren zu verwenden, und jeder hat das Gefühl, dass wir wie ArrayList eher für Schleifen verwenden und Methoden zum Durchqueren der Sammlung erhalten würden.
Anwendbare Szenarien für den Iteratormodus
Das Iteratormuster ist symbiotisch und Tod mit der Sammlung. Solange wir eine Sammlung implementieren, müssen wir im Allgemeinen gleichzeitig den Iterator der Sammlung zur Verfügung stellen, genau wie Sammlung, List, Set, Karte usw. In Java verfügen diese Sammlungen über ihre eigenen Iteratoren. Wenn wir einen so neuen Container implementieren möchten, müssen wir natürlich auch ein Iteratormuster einführen, um einen Iterator für unseren Container zu implementieren.
Da die Beziehung zwischen Containern und Iteratoren jedoch zu eng ist, bieten die meisten Sprachen Iteratoren bei der Implementierung von Containern, und die von diesen Sprachen bereitgestellten Container und Iteratoren können unsere Anforderungen in den meisten Fällen erfüllen. Daher ist es relativ selten, das Iteratormuster selbst zu praktizieren. Wir müssen nur die vorhandenen Container und Iteratoren in der Sprache verwenden.