Wzorce projektowe: Iterator(Iterator)

Teraz omówię wzorzec Iterator(Iterator), jak sama nazwa wskazuje służy do iterowania po kolekcjach, obiektach itp. To tak w dużym skrócie, dokładniej jest opisany w artykule.

 

Cel

  • Zapewnienie sekwencyjnego dostępu do obiektu lub obiektów składających się z określonej liczby elementów bez ujawniania reprezentacji wewnętrznej tych obiektów.
  • Stworzenie jednolitego interfejsu dla różnych zagregowanych(złączonych) struktur, obiektów, to się nazywa obsługa iteracji polimorficznej

 

Problem

Wzorce Iterator możesz wykorzystać np w sytuacjach kiedy masz zaimplementowane iterowanie po różnych strukturach danych ich elementów, ale jest to nieczytelne i wewnętrzna struktura jest ujawniona, wtedy lepiej utworzyć jeden abstrakcyjny interfejs dla każdej struktury, który będzie definiował co robi i będzie iterował po każdej strukturze w sposób oczywisty. Oraz klient nie musi znać jego dokładnej implementacji, wystarczy, że ten interfejs będzie tylko definiował co robi.

 

Użyj wtedy kiedy:

  • Chcesz mieć interfejs, który będzie pozwalał w jednolity i zrozumiały sposób poruszać po zbiorach, kolekcjach lub obiektach w twojej aplikacji.
  • Chcesz uzyskać dostęp do jakiejś kolekcji lub elementów jakiegoś obiektu bez ujawniania jego dokładnej implementacji.

 

Dyskusja

Wzorzec Iterator ostatnio stracił na znaczeniu kiedy pojawiły się typy generyczne chociaż wiadomo zależy też od technologii jaką wykorzystujemy w projekcie ale w większości przypadków istnieje wiele platform, które posiadają typy generyczne a typy generyczne posiadają metodę iteracji, która iteruje po elementach kolekcji np listy w .NET. Mimo to warto znać ten wzorzec, żeby wiedzieć jak to działa od środka i żebyśmy mogli tworzyć nowe interfejsy dostosowane do naszych wymagań iterujące po elementach danych.

Spójrz na przykład poniżej:

Listy mają już wewnątrz zaimplementowany wzorzec Iterator, my korzystamy z już gotowych rozwiązań a pętlą foreach wyświeltamy po kolei elementy kolekcji.

Wynik jest taki:

 

Struktura

W dziale Struktura standardowo mamy diagram UML, składa się z:

Klienta, który korzysta z klas ListCollection oraz MapCollection, które to dziedzieczą po klasie abstrakcyjnej Collection, która definiuje metodę createTraversalObject(), metoda createTraversalObject() tworzy klasę ListTraversal a klasa ListTraversal dziedziczy po interfejsie TraversalAbstraction, który ma zdefiniowane metody iterujące po kolekcji.

Iterator example

Schemat działania wzorca Iterator w kodzie wygląda mniej więcej tak:

Czyli podobne to wygląda jak z diagramu UML mamy zdefiniowany interfejs Collection, w którym jest zdefiniowana metoda createIterator(nazwaliśmy ją inaczej niż na diagramie UML createTraversalObject). Mamy klasę ListCollection, która implementuje interfejs Collection i za pomocą jej metody tworzymy klasę ListTraversal, klasa ListCollection może przypomina ci implementację innego wzorca jeśli tak to się nie mylisz jest nią Metoda fabrykująca, która jest opisana gdzieś w połowie we wpisie o wzorcu fabryka.

Klasa ListTraversal implemetuje metody iterujące po kolekcji zdefiniowane w interfejsie TraversalAbstraction. Metoda hasNext() sprawdza czy ciąg znaków na którym iterujemy się nie skończył, żebyśmy nie iterowali po pustej kolekcji, oraz metoda next() sprawdza za pomocą metody hasNext() czy kolekcja się skończyła, jeśli nie to zwracamy kolejny element z tej kolekcji.

Wynik jest taki:

 

Prototyp listy z .NET

Zrobimy bardziej rozwiniętą implementacje wzorca Iterator niż powyżej, będzie to taki prototyp list z .NET, ponieważ będzie posiadać niektóre jej funkcjonalności.

Zacznijmy od klasy zapisywania wartości w kolekcji czyli agregatu.

Oraz klasa MyIterator z zaimplementowanymi polami do iterowania po kolekcji. Po nazwach można się domyśleć co one robia.

Wywołanie tych klas w kliencie wygląda tak:

Najpierw zapisujemy dane do klasy MyAggregate, następnie wywołujemy metodę GetIterator(), żeby utworzyć instancję klasy MyIterator, żebyśmy mogli operować na danych klasy MyAggregate, na danych operujemy w pętli for, w której sprawdzamy w warunku zakończenia pętli polem IsDone element na którym operujemy w pętli czy jest ostatnim w kolekcji jeśli tak to wtedy kończymy wykonywanie pętli. Oraz na końcu sprawdzamy ile jest elementów w kolekcji. Przeanalizuj sobie na spokojnie ten przykład.

Wynik:

 

Przykład z życia wzięty

 

Przełączanie kanałów w telewizorze

Przykładem takim może być np przełączanie kanałów w telewizorze na następny lub poprzedni.

Iterator example

W kodzie zrobimy to tak jak zostało pokazane w powyższym rysunku. Kod będzie wyglądał bardzo podobnie jak z poprzedniego przykładu.

Interfejs ChannelFrequencies jak i klasa TunedChannel maja identyczną logikę jak w poprzednim przykładzie klasy IAggregate i MyAggregate, tylko nazwy klas, metod i zmiennych są inne.

Klasa ChannelIterator również ma prawie identycznę logikę jak z poprzedniego przykładu klasa MyIterator, tylko dodałem do niej pole Previos.

Tylko klient podlega dość dużej zmianie.

W pętli while sprawdzamy co wybrał klient, w zależności od wybranej opcji przesuwamy się o jedno miejsce do przodu w kolekcji kanałów lub do tyłu.

Wynik:

 

Podsumowanie

I to wszystko na temat wzorca Iterator🙂

Link do githuba ze wszystkimi przykładami:  https://github.com/Slaw145/IteratorTutorial

W następnym artykule, będzie mowa o wzorcu Łańcuch zobowiązań(Chain of Responsibility).

Standardowo, przypominam o newsletterze, którym wysyłam powiadomienia o nowych wpisach oraz dodatkowe informacje na temat, ogółem mówiąc, świecie IT.

Link do strony i grupy na fb:

-strona na fb: Devman.pl-Sławomir Kowalski

-grupa na fb: DevmanCommunity

Pytaj, komentuj pod spodem na końcu wpisu, podziel się nim, oceń go, co tam chcesz🙂 Do zobaczenia za tydzień, ale raczej za dwa tygodnie bo po prostu nie wyrabiam, chcę żeby na tym blogu była jakość a nie ilość, zobaczymy jak się z czasem wyrobie🙂

 
Jeśli ten wpis ci się przydał podziel się nim ze swoimi znajomymi :)

Post a comment

2 Comments to "Wzorce projektowe: Iterator(Iterator)"

avatar
  Subscribe  
newest oldest evaluated
Notify about
trackback

[…] ➡ Obszerny tekst na temat wzorca Iterator wraz z przykładami. […]