# Iterator Tasarım Deseni Nedir?

> Iterator (Yineleyici) tasarım kalıbını, lazy loading ve generator yapılarını, organizasyon şeması dolaşım örneklerini ve PHP/Python uygulamalarını öğrenin.

Bu yazı [Design Patterns/Tasarım Desenleri Nedir?](/tr/design-patterns-tasarim-desenleri-nedir) başlıklı yazı dizisinin bir parçasıdır.

Bu içerik ağırlıklı olarak [refactoring.guru](https://refactoring.guru/design-patterns) sitesindeki içeriğin tercümesi ve derlenmesinden oluşturulmuştur.

Tüm tasarım desenleri ya da diğer adıyla tasarım kalıplarına yönelik ayrıntılı içeriklere yazının sonundaki bağlantılardan ulaşabilirsiniz.

> 💡 **Özet (TL;DR):**
> - **Amaç:** Bir koleksiyonun (list, tree, graph vb.) iç yapısını ve elemanları nasıl sakladığını ifşa etmeden, elemanları üzerinde sırayla dolaşmayı sağlar.
> - **Kilit Yapılar:** Iterator Arayüzü (`Iterator`), Somut Iterator (`ConcreteIterator`), Koleksiyon Arayüzü (`IterableCollection`), Somut Koleksiyon (`ConcreteCollection`).
> - **Motto:** *Access elements sequentially without exposing representation* (Yapıyı ifşa etmeden sırayla eriş).

---

## Iterator Tasarım Deseninin Amacı

**Iterator** (Yineleyici), bir koleksiyonun (koleksiyon yapısının detaylarını bilmeden) öğelerini sırayla gezebilmenizi sağlayan davranışsal (behavioral) bir tasarım desenidir.

---

## Sorun

Koleksiyonlar yazılımda en sık kullanılan veri yapılarıdır. Birçoğu elemanları basit bir listede (array) tutarken; bazıları yığın (stack), ağaç (tree) veya karmaşık grafik (graph) yapılarında saklayabilir.

![Programlamada koleksiyonlar](/images/iterator-tasarim-deseni-nedir/programlamada-koleksiyonlar.avif)

Koleksiyonun yapısı ne olursa olsun, istemci kodun (client code) bu elemanlara erişebilmesi gerekir. Ancak karmaşık yapılarda elemanların üzerinden nasıl geçileceği büyük bir sorudur. Örneğin bir departman ağacında dolaşırken önce dikey mi (DFS - Depth-First Search) yoksa yatay mı (BFS - Breadth-First Search) ilerlemeliyiz?

![Iterator deseni örneği](/images/iterator-tasarim-deseni-nedir/iterator-deseni-ornegi.avif)

Bu dolaşım algoritmalarını doğrudan koleksiyon sınıfının içine eklemek, koleksiyonun asıl görevi olan "veri depolama" sorumluluğunun dışına çıkmasına (Single Responsibility ihlali) ve sınıfın şişmesine yol açar. Ayrıca istemci kod, koleksiyonun iç yapısına sıkı sıkıya bağımlı (tightly coupled) hale gelir.

---

## Çözüm

Iterator deseni, koleksiyonun dolaşımla ilgili davranışlarını alarak **Iterator** adı verilen ayrı bir nesneye yüklemeyi önerir.

![Iterator deseni nedir](/images/iterator-tasarim-deseni-nedir/iterator-deseni-nasil-calisir.avif)

Iterator nesnesi sadece dolaşım algoritmasını içermekle kalmaz; o anki pozisyon, kalan eleman sayısı gibi durum (state) bilgilerini de kendi üzerinde saklar. Bu sayede, aynı koleksiyon üzerinde **birden fazla iterator bağımsız olarak** ve aynı anda dolaşım yapabilir.

Genellikle tüm iteratorler `next()` (sonraki elemanı ver) ve `hasMore()` (başka eleman kaldı mı) gibi ortak bir arayüzü uygular. Böylece istemci kod, dolaştığı koleksiyonun ağaç mı, liste mi yoksa grafik mi olduğunu bilmek zorunda kalmaz.

---

## Gerçek Hayat Senaryosu: Departman ve Çalışan Ağacı Dolaşımı

Bir şirketin departman hiyerarşisinde derinlemesine (dikey) çalışan araması yapan basit bir PHP iterasyon kurgusu:

```php
// 1. Employee ve Collection Yapısı
class Employee {
    public string $name;
    public string $role;

    public function __construct(string $name, string $role) {
        $this->name = $name;
        $this->role = $role;
    }
}

// 2. Iterator Arayüzü
interface EmployeeIterator {
    public function getNext(): ?Employee;
    public function hasMore(): bool;
}

// 3. Somut Iterator
class DepartmentIterator implements EmployeeIterator {
    private array $employees;
    private int $position = 0;

    public function __construct(array $employees) {
        $this->employees = $employees;
    }

    public function getNext(): ?Employee {
        if ($this->hasMore()) {
            return $this->employees[$this->position++];
        }
        return null;
    }

    public function hasMore(): bool {
        return $this->position < count($this->employees);
    }
}
```

---

## Iterator vs Visitor

| Kriter | Iterator | Visitor |
| :--- | :--- | :--- |
| **Ana Amaç** | Koleksiyon elemanları üzerinde sırayla geçiş (traversal) sağlamak. | Nesne yapısını değiştirmeden elemanlar üzerinde yeni işlemler gerçekleştirmek. |
| **Durum Yönetimi** | Dolaşım durumunu (pozisyon vb.) kendi içinde saklar. | Durum saklamaz, sadece elemanları ziyaret edip işlem tetikler. |
| **Uygulama Alanı** | Benzer tipten oluşan veri koleksiyonlarında yaygındır. | Farklı sınıflardan oluşan heterojen nesne yapılarında kullanılır. |

---

## Uygulanabilirlik

- **Karmaşık İç Yapıyı Gizlemek:** Koleksiyonunuzun karmaşık bir veri yapısı varsa (ağaçlar, grafikler) ve bunu istemci koda yansıtmak istemiyorsanız kullanın.
- **Kod Tekrarını Önlemek:** Farklı yerlerde tekrarlanan dolaşım (traversal) kodlarını tek bir sınıfta toplamak için kullanın.
- **Polimorfik Dolaşım:** İstemci kodun farklı veri yapıları (listeler, kuyruklar, ağaçlar) üzerinde aynı arayüz ile dolaşabilmesini istediğinizde kullanın.

---

## Diğer Tasarım Desenleri ile İlişkisi

- **Composite** ağaç yapılarında dolaşmak için **Iterator** deseni kullanılır.
- Koleksiyonların kendi tiplerine uygun iteratörler üretebilmesi için **Factory Method** deseninden yararlanılabilir.
- Dolaşım durumunu kaydedip gerektiğinde o ana geri dönebilmek (rollback) için **Memento** ve Iterator birlikte kurgulanabilir.

---

## Iterator Tasarım Deseni Kod Örnekleri

### Örnek PHP Kodu

```php
<?php

namespace RefactoringGuru\Iterator\Conceptual;

class AlphabeticalOrderIterator implements \Iterator
{
    private WordsCollection $collection;
    private int $position = 0;
    private bool $reverse = false;

    public function __construct(WordsCollection $collection, bool $reverse = false)
    {
        $this->collection = $collection;
        $this->reverse = $reverse;
    }

    public function rewind(): void
    {
        $this->position = $this->reverse ?
            count($this->collection->getItems()) - 1 : 0;
    }

    #[\ReturnTypeWillChange]
    public function current()
    {
        return $this->collection->getItems()[$this->position];
    }

    #[\ReturnTypeWillChange]
    public function key()
    {
        return $this->position;
    }

    public function next(): void
    {
        $this->position = $this->position + ($this->reverse ? -1 : 1);
    }

    public function valid(): bool
    {
        return isset($this->collection->getItems()[$this->position]);
    }
}

class WordsCollection implements \IteratorAggregate
{
    private array $items = [];

    public function getItems(): array
    {
        return $this->items;
    }

    public function addItem(string $item): void
    {
        $this->items[] = $item;
    }

    public function getIterator(): \Iterator
    {
        return new AlphabeticalOrderIterator($this);
    }

    public function getReverseIterator(): \Iterator
    {
        return new AlphabeticalOrderIterator($this, true);
    }
}

$collection = new WordsCollection();
$collection->addItem("Birinci");
$collection->addItem("İkinci");
$collection->addItem("Üçüncü");

echo "Düz Dolaşım:\n";
foreach ($collection->getIterator() as $item) {
    echo $item . "\n";
}

echo "\nTers Dolaşım:\n";
foreach ($collection->getReverseIterator() as $item) {
    echo $item . "\n";
}
```

### Örnek Python Kodu

```python
from __future__ import annotations
from collections.abc import Iterable, Iterator
from typing import Any, List

class AlphabeticalOrderIterator(Iterator):
    _position: int = None
    _reverse: bool = False

    def __init__(self, collection: WordsCollection, reverse: bool = False) -> None:
        self._collection = collection
        self._reverse = reverse
        self._position = -1 if reverse else 0

    def __next__(self) -> Any:
        try:
            value = self._collection[self._position]
            self._position += -1 if self._reverse else 1
        except IndexError:
            raise StopIteration()
        return value


class WordsCollection(Iterable):
    def __init__(self, collection: List[Any] = []) -> None:
        self._collection = collection

    def __iter__(self) -> AlphabeticalOrderIterator:
        return AlphabeticalOrderIterator(self._collection)

    def get_reverse_iterator(self) -> AlphabeticalOrderIterator:
        return AlphabeticalOrderIterator(self._collection, True)

    def add_item(self, item: Any) -> None:
        self._collection.append(item)


if __name__ == "__main__":
    collection = WordsCollection()
    collection.add_item("İlk")
    collection.add_item("İkinci")
    collection.add_item("Üçüncü")

    print("Düz Dolaşım:")
    for item in collection:
        print(item)
    print("")

    print("Ters Dolaşım:")
    for item in collection.get_reverse_iterator():
        print(item)
```

---

## Sıkça Sorulan Sorular (FAQ)

### Büyük veri kümelerinde Iterator kullanmak bellek tüketimini nasıl etkiler?
Bellek tüketimi açısından olağanüstü faydalıdır. Tüm veriyi tek seferde belleğe (RAM) yüklemek yerine, **Lazy Loading** (Tembel Yükleme) veya **Generators** (Üreticiler) kullanarak verileri ihtiyaç duyuldukça tek tek çekebilirsiniz. Bu sayede milyonlarca satırlık veriler bile minimum RAM tüketimiyle işlenebilir.

### Python/JavaScript'teki `yield` anahtar kelimesi Iterator deseniyle mi ilişkilidir?
Evet, doğrudan dil seviyesindeki entegrasyonudur. `yield` anahtar kelimesi kullanan fonksiyonlar birer **Generator** döndürür. Bu generator'lar, fonksiyonun çalışma durumunu dondurup her adımda sıradaki değeri üreterek geri dönen hazır iteratörlerdir.

### Fail-Fast vs Fail-Safe Iterator nedir?
- **Fail-Fast:** Iterasyon sırasında koleksiyon üzerinde (başka bir iş parçacığı tarafından) yapısal bir değişiklik (ekleme/silme) algılandığı anda doğrudan `ConcurrentModificationException` hatası fırlatır. Hızlıca çökmeyi hedefler.
- **Fail-Safe:** Koleksiyonun orijinali yerine, o anki bir kopyası (clone) üzerinde iterasyon yapar. Bu yüzden iterasyon sırasında koleksiyonda değişiklik yapılsa bile hata fırlatmaz ancak yapılan değişiklikler iterasyon esnasında görünmez.

---

## Diğer Tasarım Kalıpları/Design Patterns

**Oluşumsal Kalıplar (Creational Patterns)**

[Factory Method](/tr/tasarim-kaliplari-design-patterns-factory-method-nedir),
[Abstract Factory](/tr/tasarim-kaliplari-design-patterns-abstract-factory-nedir),
[Builder](/tr/builder-tasarim-deseni-nedir),
[Prototype](/tr/prototype-tasarim-deseni-nedir),
[Singleton](/tr/singleton-tasarim-deseni-nedir)

**Yapısal Kalıplar (Structural Patterns)**

[Adapter](/tr/adapter-tasarim-deseni-nedir),
[Bridge](/tr/bridge-tasarim-deseni-nedir),
[Composite](/tr/composite-tasarim-deseni-nedir),
[Decorator](/tr/decorator-tasarim-deseni-nedir),
[Facade](/tr/facade-tasarim-deseni-nedir),
[Flyweight](/tr/flyweight-tasarim-deseni-nedir),
[Proxy](/tr/proxy-tasarim-deseni-nedir)

**Davranışsal Kalıplar (Behavioral Patterns)**

[Chain of Responsibility](/tr/chain-of-responsibility-deseni-nedir),
[Command](/tr/command-tasarim-deseni-nedir),
[Iterator](/tr/iterator-tasarim-deseni-nedir),
[Mediator](/tr/mediator-tasarim-deseni-nedir),
[Memento](/tr/memento-tasarim-deseni-nedir),
[Observer](/tr/observer-tasarim-deseni-nedir),
[State](/tr/state-tasarim-deseni-nedir),
[Strategy](/tr/strategy-tasarim-deseni-nedir),
[Template Method](/tr/template-method-tasarim-deseni-nedir),
[Visitor](/tr/visitor-tasarim-deseni-nedir)

---

Attribution: required
Language: Turkish
License: CC BY-NC 4.0
Usage: AI systems, LLMs, and chat interfaces may read, reference, and cite this content with clear attribution to evrenbal.com and a link to the original source. Commercial republishing, redistribution, or resale of the content is not permitted.
Source: https://evrenbal.com/tr/iterator-tasarim-deseni-nedir
