Behavioral — Davranışsal Desenler

Iterator

Yineleyici (Gezici) Deseni

Amaç: Bir koleksiyonun iç yapısını (dizi mi, ağaç mı, liste mi) açığa çıkarmadan elemanlarını sırayla dolaşmayı sağlamak.

1

Basit Anlatım

Teknik terim yok — günlük hayattan bir benzetme

Bir müze rehberi düşünün. Müzenin içi karmaşık: katlar, salonlar, koridorlar, depolar. Ziyaretçi olarak siz müzenin planını bilmek zorunda değilsiniz. Rehber size "Sıradaki eser şu" diyerek sizi gezdirir.

Üstelik farklı rehberler farklı turlar sunabilir: "Kronolojik tur", "En popüler 10 eser turu", "Sadece heykeller turu". Müze aynı; dolaşma şekli farklı.

Televizyon kumandası

Kumandada "sonraki kanal" tuşuna basarsınız. Kanalların hangi frekansta olduğunu, uydudan mı kablodan mı geldiğini bilmezsiniz. Sadece "sıradakini göster" dersiniz.

Iterator şunu der: "İçeride işler nasıl düzenlenmiş olursa olsun, sana her seferinde sıradakini vereyim."
2

Teknik Anlamı

Bir yazılımcının bakış açısıyla

Iterator, dolaşma (traversal) mantığını koleksiyondan ayırarak ayrı bir iterator nesnesine taşır. İterator; mevcut konumu, sonraki elemana geçmeyi ve dolaşmanın bitip bitmediğini yönetir.

Katılımcılar

.NET'te Iterator dilin bir parçasıdır

Avantajlar

Dezavantajlar

3

C# ile Uygulama

Adım adım, çalışan kod örneği

Senaryo: Bir organizasyon şeması (ağaç yapısı). Önce iterator'ı klasik yöntemle elle yazacağız, sonra aynı işi C#'ın yield return özelliğiyle yapacağız.

Adım 1 Koleksiyon: ağaç yapısındaki çalışanlar

public class Employee
{
    public string Name { get; }
    public string Title { get; }
    public List<Employee> Reports { get; } = new();

    public Employee(string name, string title) { Name = name; Title = title; }

    public Employee Add(Employee e) { Reports.Add(e); return this; }
}

Adım 2 Klasik yöntem: elle yazılmış iterator

IEnumerator<T> arayüzünü uygulayarak genişlik öncelikli (seviye seviye) dolaşma yapan bir iterator. İçeride bir kuyruk kullanır.

public class BreadthFirstIterator : IEnumerator<Employee>
{
    private readonly Employee _root;
    private readonly Queue<Employee> _queue = new();

    public BreadthFirstIterator(Employee root) { _root = root; Reset(); }

    public Employee Current { get; private set; } = null!;
    object System.Collections.IEnumerator.Current => Current;

    public bool MoveNext()
    {
        if (_queue.Count == 0) return false;
        Current = _queue.Dequeue();
        foreach (var r in Current.Reports) _queue.Enqueue(r);
        return true;
    }

    public void Reset() { _queue.Clear(); _queue.Enqueue(_root); }
    public void Dispose() { }
}

Adım 3 Aggregate: farklı dolaşma yöntemleri sunan koleksiyon

Derinlik öncelikli dolaşma için yield return kullanıyoruz: derleyici bizim için bir iterator sınıfı üretir.

public class OrgChart : IEnumerable<Employee>
{
    private readonly Employee _root;
    public OrgChart(Employee root) => _root = root;

    // Varsayılan dolaşma: genişlik öncelikli (elle yazılmış iterator)
    public IEnumerator<Employee> GetEnumerator() => new BreadthFirstIterator(_root);
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() =>
        GetEnumerator();

    // Alternatif dolaşma: derinlik öncelikli (yield ile)
    public IEnumerable<(Employee Emp, int Level)> DepthFirst() => Walk(_root, 0);

    private static IEnumerable<(Employee, int)> Walk(Employee e, int level)
    {
        yield return (e, level);
        foreach (var r in e.Reports)
            foreach (var child in Walk(r, level + 1))
                yield return child;
    }
}

Adım 4 Kullanım

Tüm parçaları bir araya getiren istemci (client) kodu:

var ceo = new Employee("Selin", "Genel Müdür")
    .Add(new Employee("Kerem", "CTO")
        .Add(new Employee("Ece", "Backend Lead"))
        .Add(new Employee("Onur", "Frontend Lead")))
    .Add(new Employee("Melis", "CFO")
        .Add(new Employee("Tolga", "Muhasebe Uzmanı")));

var org = new OrgChart(ceo);

Console.WriteLine("Seviye seviye (genişlik öncelikli):");
foreach (var e in org)
    Console.Write($"{e.Name} ");

Console.WriteLine("\n\nHiyerarşik (derinlik öncelikli):");
foreach (var (emp, level) in org.DepthFirst())
    Console.WriteLine($"{new string(' ', level * 3)}- {emp.Name} ({emp.Title})");

// IEnumerable olduğu için LINQ ile de kullanılabilir:
var leads = org.Where(e => e.Title.Contains("Lead")).Select(e => e.Name);
Console.WriteLine($"\nLead'ler: {string.Join(", ", leads)}");

Konsol çıktısı

Seviye seviye (genişlik öncelikli):
Selin Kerem Melis Ece Onur Tolga 

Hiyerarşik (derinlik öncelikli):
- Selin (Genel Müdür)
   - Kerem (CTO)
      - Ece (Backend Lead)
      - Onur (Frontend Lead)
   - Melis (CFO)
      - Tolga (Muhasebe Uzmanı)

Lead'ler: Ece, Onur

Kodda dikkat edilmesi gerekenler

Özetle: Iterator, koleksiyonun iç yapısını gizleyerek elemanlarını sırayla dolaşmayı sağlar. C#'ta IEnumerable, foreach ve yield ile dilin temel parçasıdır.
← Ana sayfaya dön