Menu
Coddy logo textTech

Yineleyici Kalıbı

Coddy'nin Java Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 76 / 87.

Iterator Deseni (Iterator Pattern), bir koleksiyonun öğelerine, temel yapısını açığa çıkarmadan sıralı bir şekilde erişmenin bir yolunu sağlayan davranışsal bir tasarım desenidir. İster bir dizi, bağlı liste veya ağaç ile çalışıyor olun, yineleyici (iterator) size öğeler arasında gezinmek için tek tip bir yol sunar.

Desen, gezinme (traversal) mantığını koleksiyonun kendisinden ayırır. İki ana bileşenden oluşur: elemanlar arasında gezinmek için yöntemler tanımlayan bir Iterator arayüzü ve koleksiyonu için yineleyiciler (iterators) oluşturan bir Iterable (veya Aggregate):

interface Iterator<T> {
    boolean hasNext();
    T next();
}

interface Container<T> {
    Iterator<T> createIterator();
}

class BookShelf implements Container<String> {
    private String[] books;
    private int count = 0;
    
    public BookShelf(int size) {
        books = new String[size];
    }
    
    public void addBook(String book) {
        books[count++] = book;
    }
    
    public Iterator<String> createIterator() {
        return new BookIterator();
    }
    
    private class BookIterator implements Iterator<String> {
        private int index = 0;
        
        public boolean hasNext() {
            return index < count;
        }
        
        public String next() {
            return books[index++];
        }
    }
}

Yineleyici kendi gezinme durumunu korur, bu da birden fazla yineleyicinin aynı koleksiyonu bağımsız olarak gezmesine olanak tanır. İstemciler, koleksiyonun verilerini nasıl sakladığını bilmeden yineleyiciyi kullanır:

BookShelf shelf = new BookShelf(3);
shelf.addBook("Design Patterns");
shelf.addBook("Clean Code");

Iterator<String> iterator = shelf.createIterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

Java'nın yerleşik Iterable ve Iterator arayüzleri tam olarak bu deseni takip eder; bu nedenle Iterable arayüzünü uygulayan herhangi bir sınıfla geliştirilmiş for döngülerini (enhanced for-loops) kullanabilirsiniz. Iterator Deseni, birden fazla gezinme yöntemi sağlamanız veya karmaşık dahili yapıları istemci kodundan gizlemeniz gerektiğinde gereklidir.

challenge icon

Görev

Kolay

Iterator Desenini kullanarak bir çalma listesi sistemi oluşturalım! Şarkıları depolayan ve şarkıların dahili olarak nasıl saklandığını ifşa etmeden bunlar arasında sırayla gezinmek için özel bir yineleyici (iterator) sağlayan bir müzik çalma listesi oluşturacaksınız. Bu, kullanıcıların koleksiyonunuzda temiz ve tek tip bir arayüz üzerinden gezinmesine olanak tanıyan Iterator Deseni için mükemmel bir kullanım durumudur.

Kodunuzu dört dosya halinde düzenleyeceksiniz:

  • Iterator.java: İki yönteme sahip genel Iterator<T> arayüzünüzü tanımlayın: daha fazla öğe olup olmadığını belirten bir boolean döndüren hasNext() ve T türündeki bir sonraki öğeyi döndüren next().
  • Playlist.java: Şarkılarınızı tutan toplu (aggregate) sınıfı oluşturun. Playlist sınıfınız, şarkıları sabit kapasiteli (yapıcıya iletilen) bir String dizisinde saklamalı ve kaç şarkı eklendiğini takip etmelidir. Çalma listesine şarkı eklemek için bir addSong(String song) yöntemi ekleyin.

    Playlist sınıfınızın, bir Iterator<String> döndüren bir createIterator() yöntemine ihtiyacı vardır. Bunu, Iterator arayüzünüzü uygulayan PlaylistIterator adında özel bir iç sınıf (inner class) oluşturarak gerçekleştirin. Bu dahili yineleyici, kendi dizin (index) konumunu korur ve şarkı dizisi boyunca ilerleyerek her şarkıyı sırayla döndürür.

  • Song.java: Bir şarkı adını sarmalayan basit bir Song sınıfı oluşturun. Şarkı adını (String) alan bir yapıcıya, bir getTitle() yöntemine ve "Playing: " + title (yani Playing: [title]) döndüren bir toString() yöntemine sahip olmalıdır.
  • Main.java: Yineleyici sisteminizi bir araya getirin! Bir girdi alacaksınız: virgülle ayrılmış şarkı adlarından oluşan bir liste (örneğin: Bohemian Rhapsody,Stairway to Heaven,Hotel California).

    10 şarkı kapasiteli bir Playlist oluşturun. Girdiyi ayrıştırın ve her şarkı adını çalma listesine ekleyin. Ardından çalma listesinden bir yineleyici alın ve bunu tüm şarkılar arasında gezinmek için kullanın; her birini bir Song nesnesi içinde yazdırın (bu, Playing: [title] olarak görüntülenecektir).

    Tüm şarkılar arasında gezindikten sonra, yeni bir satıra Playlist complete! yazdırın.

Bir girdi alacaksınız: virgülle ayrılmış şarkı adlarından oluşan bir dize.

Örneğin, Yesterday,Imagine,Let It Be girdisiyle çıktınız şöyle olacaktır:

Playing: Yesterday
Playing: Imagine
Playing: Let It Be
Playlist complete!

Main sınıfınızın, temel dizi yapısı hakkında hiçbir şey bilmeden çalma listesinde gezinmek için yineleyicinin hasNext() ve next() yöntemlerini nasıl kullandığına dikkat edin. Yineleyici, tüm gezinme mantığını kapsülleyerek koleksiyonun dahili temsilini istemci kodundan gizli tutar!

Kopya kağıdı

Iterator (Yineleyici) Deseni, bir koleksiyonun öğelerine, temel yapısını açığa çıkarmadan sıralı bir şekilde erişmenin bir yolunu sağlayan davranışsal bir tasarım desenidir.

Bu desen, iki ana bileşen kullanarak gezinme mantığını koleksiyonun kendisinden ayırır:

  • Iterator arayüzü: öğeler arasında gezinmek için yöntemleri tanımlar
  • Iterable/Container: koleksiyonu için yineleyiciler oluşturur

Temel Yapı

interface Iterator<T> {
    boolean hasNext();
    T next();
}

interface Container<T> {
    Iterator<T> createIterator();
}

Uygulama Örneği

class BookShelf implements Container<String> {
    private String[] books;
    private int count = 0;
    
    public BookShelf(int size) {
        books = new String[size];
    }
    
    public void addBook(String book) {
        books[count++] = book;
    }
    
    public Iterator<String> createIterator() {
        return new BookIterator();
    }
    
    private class BookIterator implements Iterator<String> {
        private int index = 0;
        
        public boolean hasNext() {
            return index < count;
        }
        
        public String next() {
            return books[index++];
        }
    }
}

Kullanım

BookShelf shelf = new BookShelf(3);
shelf.addBook("Design Patterns");
shelf.addBook("Clean Code");

Iterator<String> iterator = shelf.createIterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

Yineleyici kendi gezinme durumunu korur, bu da birden fazla yineleyicinin aynı koleksiyon üzerinde bağımsız olarak gezinmesine olanak tanır. Java'nın yerleşik Iterable ve Iterator arayüzleri bu deseni takip ederek gelişmiş for-döngülerini (enhanced for-loops) mümkün kılar.

Kendin dene

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        
        // TODO: 10 şarkı kapasiteli bir Playlist oluşturun
        
        // TODO: Girdiyi ayrıştırın (virgülle ayrılmış) ve her şarkı başlığını playlist'e ekleyin
        
        // TODO: createIterator() kullanarak playlist'ten bir iterator elde edin
        
        // TODO: Tüm şarkılar arasında gezinmek için iterator'ı kullanın
        // Her şarkı için, onu bir Song nesnesine sarın ve yazdırın
        
        // TODO: Tüm şarkılar arasında gezindikten sonra "Playlist complete!" yazdırın
    }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler