Iterator (Entwurfsmuster)

Iterator (Entwurfsmuster)

Der Iterator ist ein Entwurfsmuster aus dem Bereich der Softwareentwicklung und gehört zu der Kategorie der Verhaltensmuster (Behavioural Patterns). Das Muster ist eines der sogenannten GoF-Muster (siehe Viererbande). Es stellt Möglichkeiten zur Verfügung, auf Elemente einer aggregierten Struktur sequenziell zuzugreifen, ohne die Struktur zu enthüllen.

Das Muster ist auch als Cursor bekannt. Mitunter wird durch Wahl des einen oder anderen Begriffes ein Unterschied im Verhalten impliziert.

Inhaltsverzeichnis

Verwendung

In der Praxis werden häufig Objekte zu einer Sammlung zusammengefasst. Auf die Elemente solch einer Sammlung soll möglichst generisch und ohne Rücksicht auf die Implementierungsdetails zugegriffen werden können.

UML-Diagramm

Klassendiagramm

Das Diagramm ist nur als grobes Beispiel zu sehen. Die konkrete Realisierung kann stark abweichen:

  • Anstelle der Ableitungspfeile kann z.B. die Realisierung eines Konzeptes stehen. D.h. es gibt gar keine Basisklasse, lediglich eine unverbindliche Vorgabe.
  • Die Methoden sind nicht in jedem Fall sinnvoll. Zurueck() oder IstFertig() sind nicht immer realisierbar.
  • Navigationpfeile zwischen KonkretesAggregat und KonkreterIterator können nur in eine Richtung gehen oder ganz fehlen.

Akteure

  • Iterator definiert die Schnittstelle zum Zugriff auf die Elemente und zum Traversieren des Aggregates.
  • Konkreter Iterator implementiert diese Schnittstelle und speichert die Position im Aggregat.
  • Aggregat definiert die Schnittstelle zum Erzeugen eines Iterators. Oft enthält die Schnittstelle auch Methoden zum Erzeugen von Iteratoren die auf spezielle Elemente zeigen, wie z.B. erstes, letztes oder ein Element mit bestimmten Eigenschaften.
  • Konkretes Aggregat implementiert diese Schnittstelle.

Vorteile

Die Implementierung der zu Grunde liegenden Datenstruktur bleibt verborgen.

Nachteile

Je nach Variante der Implementierung können sich Nachteile durch erhöhte Laufzeit- und Speicherkosten ergeben.

  • Bei polymorphen Iteratoren muss man den Preis für virtuelle Methoden zahlen.
  • Wenn der Iterator sein Aggregat kennt und/oder das Aggregat über seine Iteratoren Buch führt, verteuern sich vor allem das Erzeugen und Vernichten von Aggregaten. (Im Gegenzug erhält man eine höhere Sicherheit)

Implementierung

Aufgrund einiger Designentscheidungen ergeben sich Iterator-Varianten mit verschiedenen Eigenschaften:

Wer steuert die Iteration?

Bei einem externen Iterator steuert der Klient die Iteration. Der Klient muss dafür sorgen, dass der Iterator weiterrückt.

Ein interner Iterator tut dies selbst. Dazu muss ihm die Operation übergeben werden, die er auf das aktuelle Element anwenden soll. Interne Iteratoren werden oft gar nicht als solche erkannt oder bezeichnet, da die Iteration nicht sichtbar ist oder aber über externe Iteratoren realisiert ist.

(Booch nennt den externen Iterator aktiv und den internen passiv.)

Traversionsalgorithmus

Der Traversionsalgorithmus kann durch den Iterator oder das Aggregat vorgegeben werden. Im letzteren Fall wird oft von einem Cursor gesprochen.

Robustheit

Wenn das Aggregat während der Traversion verändert wird, kann das zu falschen Ergebnissen oder gar zum Programmabsturz führen. Ein robuster Iterator ist gegen Modifikationen des Aggregats gesichert. Typischerweise werden dazu die Iteratoren beim Aggregat registriert. Das führt zu höheren Kosten beim Erzeugen der Iteratoren, aber auch beim Ändern des Aggregates.

Polymorphie

Polymorphe Iteratoren bieten eine hohe Flexibilität. Da Iteratoren meist in Schleifen verwendet werden, sind die Kosten dafür allerdings sehr hoch.

Nulliteratoren

Je nach Implementation kann es, in Analogie zum Null-Zeiger, einen Nulliterator geben. Dieser signalisiert das Ende einer Iteration oder einen ungültigen Iterator. Das ist recht bequem in der Benutzung, da man einen Iterator seine Gültigkeit "ansieht", aber die Implementation wird dadurch u. U. komplizierter.

Daher wurde z. B. in der C++-Standardbibliothek diese Alternative gewählt. Dabei besitzt jedes Aggregat seinen eigenen Nulliterator mit dem man dann den jeweiligen Iterator vergleichen muss.

Privilegien

Ein Iterator kann privilegierten Zugriff auf die Interna des Aggregates besitzen. Das ist bei komplexen Datenstrukturen teilweise nicht zu vermeiden. Allerdings wird dadurch die Implementation neuer Traversionsalgorithmen erschwert oder gar verhindert.

Beispiel

Ein einfacher Fall eines externen Iterators wäre etwa (in Java):

class ObjectIterator {
  private Object[] m_source;
  private int m_current;
 
  public ObjectIterator(Object[] source) {
    m_source = source;
  }
 
  public boolean hasNext() {
    return m_current < m_source.length;
  }
 
  public Object next() {
    return m_source[m_current++];
  }
}

Anwendung:

Object[] myList = new Object[] {new Integer(1), new Integer(2), new Integer(3)};
ObjectIterator iterator = new ObjectIterator(myList);
while(iterator.hasNext()) {
  System.out.println(iterator.next());
}

Eine andere Variation dieses Entwurfsmusters wäre ein interner Iterator:

class MyObjectIterator extends ObjectIterator {
  public MyObjectIterator(Object[] source) {
    super(source);
  }
 
  public void print() {
    while(hasNext()) {
      System.out.println(next());
    }
  }
 
  public void apply(ObjectHandler handler) {
    while(hasNext()) {
      handler.handle(next());
    }
  }
}
 
interface ObjectHandler {
  public void handle(Object o);
}

Anwendung:

class MyObjectHandler implements ObjectHandler {
  public void handle(Object o) {
    System.out.println(o);
  }
}
 
Object[] myList = new Object[] {new Integer(1), new Integer(2), new Integer(3)};
MyObjectIterator iterator = new MyObjectIterator(myList);
iterator.print();
iterator.apply(new MyObjectHandler());

Ein interner Iterator kapselt die Iteration selber und macht sie so im gesamten Programm einfach und konsistent wiederverwendbar, ohne sie wie im Fall eines externen Iterators immer wieder neu programmieren zu müssen. Durch Anwendung des Strategie Entwurfsmusters lässt sich der Algorithmus auch einfach austauschen, wie in der letzten Beispielzeile gezeigt.

Obwohl sich diese Beispiele mit sequenziellem Zugriff begnügen, sind natürlich auch Iteratoren mit wahlfreiem Zugriff möglich. Viele Implementierungen bieten zusätzlich die Möglichkeit die iterierte Sammlung direkt zu verändern, etwa durch Entfernen des aktuellen Elementes.

Die STL enthält Iteratoren für ihre Container.

Verwandte Entwurfsmuster

  • Kompositum, als Variante eines zusammengesetzten Objektes, benötigt Iteratoren zum Traversieren.
  • Polymorphe Iteratoren werden durch Fabrikmethoden erzeugt.

Siehe auch

Wikibooks Wikibooks: Muster: Iterator – Lern- und Lehrmaterialien

Wikimedia Foundation.

Игры ⚽ Поможем сделать НИР

Schlagen Sie auch in anderen Wörterbüchern nach:

  • Iterator — Der Begriff Iterator stammt aus dem Bereich der Softwareentwicklung und bezeichnet einen Zeiger, mit dem über die Elemente einer Liste bzw. durch die Elemente einer Menge iteriert werden kann. Der Iterator wird insbesondere im Bereich der… …   Deutsch Wikipedia

  • Entwurfsmuster (Buch) — Entwurfsmuster. Elemente wiederverwendbarer objektorientierter Software, ISBN 3 8273 2199 9 (Originaltitel: Design Patterns. Elements of Reusable Object Oriented Software.) ist ein 1994 von Erich Gamma, Richard Helm, Ralph Johnson und John… …   Deutsch Wikipedia

  • Entwurfsmuster — (engl. design patterns) sind bewährte Lösungsschablonen für wiederkehrende Entwurfsprobleme in Softwarearchitektur und Softwareentwicklung. Sie stellen damit eine wiederverwendbare Vorlage zur Problemlösung dar, die in einem bestimmten… …   Deutsch Wikipedia

  • Beobachter (Entwurfsmuster) — Der Observer (Beobachter, Listener) ist ein Entwurfsmuster aus dem Bereich der Softwareentwicklung und gehört zu der Kategorie der Verhaltensmuster (Behavioural Patterns). Es dient zur Weitergabe von Änderungen an einem Objekt an von diesem… …   Deutsch Wikipedia

  • Proxy (Entwurfsmuster) — Der Proxy, auch Stellvertreter genannt, ist ein Entwurfsmuster aus dem Bereich der Softwareentwicklung und gehört zu der Kategorie der Strukturmuster (Structural Patterns). Das Muster dient zum Verschieben der Kontrolle über ein Objekt auf ein… …   Deutsch Wikipedia

  • Bridge (Entwurfsmuster) — Eine Brücke (engl. Bridge) ist in der Softwareentwicklung ein Entwurfsmuster und gehört zur Kategorie der Strukturmuster (Structural Patterns). Das Muster dient zur Trennung der Implementierung von ihrer Abstraktion (Schnittstelle), wodurch beide …   Deutsch Wikipedia

  • Builder (Entwurfsmuster) — Der Erbauer (englisch Builder) ist ein Entwurfsmuster aus dem Bereich der Softwareentwicklung und gehört zur Kategorie der Erzeugungsmuster (Creational Patterns). Es trennt die Konstruktion komplexer Objekte von deren Repräsentationen, wodurch… …   Deutsch Wikipedia

  • Composite (Entwurfsmuster) — Das Kompositum (engl. Composite) ist ein Entwurfsmuster aus dem Bereich der Softwareentwicklung und gehört zu der Kategorie der Strukturmuster (Structural Patterns). Es wird angewendet um Teil Ganzes Hierarchien zu repräsentieren, indem Objekte… …   Deutsch Wikipedia

  • Einzelstück (Entwurfsmuster) — Das Singleton (auch Einzelstück genannt) ist ein in der Softwareentwicklung eingesetztes Entwurfsmuster und gehört zur Kategorie der Erzeugungsmuster (engl. Creational Patterns). Es verhindert, dass von einer Klasse mehr als ein Objekt erzeugt… …   Deutsch Wikipedia

  • Facade (Entwurfsmuster) — Fassade (engl. facade) ist ein Entwurfsmuster aus dem Bereich der Softwareentwicklung und gehört zu der Kategorie der Strukturmuster (Structural Patterns). Es bietet eine einheitliche und meist vereinfachte Schnittstelle zu einer Menge von… …   Deutsch Wikipedia

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”