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.
Görev
KolayIterator 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 genelIterator<T>arayüzünüzü tanımlayın: daha fazla öğe olup olmadığını belirten bir boolean döndürenhasNext()ve T türündeki bir sonraki öğeyi döndürennext().Playlist.java: Şarkılarınızı tutan toplu (aggregate) sınıfı oluşturun.Playlistsı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 biraddSong(String song)yöntemi ekleyin.Playlist sınıfınızın, bir
Iterator<String>döndüren bircreateIterator()yöntemine ihtiyacı vardır. Bunu, Iterator arayüzünüzü uygulayanPlaylistIteratoradı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 birSongsınıfı oluşturun. Şarkı adını (String) alan bir yapıcıya, birgetTitle()yöntemine ve"Playing: " + title(yaniPlaying: [title]) döndüren birtoString()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
}
}
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
1OOP Temelleri
Harici DosyalarOOP'ye GirişSınıflar ve Nesnelerthis Anahtar KelimesiMetotlarAlanlar (Öznitelikler)Yapıcı MetotYapıcı Metot Aşırı YüklemeÖzet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtım (extends)super Anahtar KelimesiMetot Geçersiz Kılma (@Override)Yapıcı Metot ZincirlemeObject SınıfıTekli ve Çok Seviyeli KalıtımNeden Çoklu Sınıf Kalıtımı Yok?Özet - Çalışan Hiyerarşisi7Özel Metotlar ve Object Sınıfı
toString() Metoduequals() ve hashCode()clone() MetoducompareTo() ve ComparableComparator ArayüzüÖzet - Özel Sıralama2Erişim Belirleyiciler ve Kapsülleme
Erişim Seviyelerine Genel BakışGetter ve Setter MetotlarıBilgi Gizlemefinal Anahtar KelimesiÖzet - Banka Hesabı Yöneticisi5Polimorfizm
Metot Aşırı Yükleme TemelleriMetot Geçersiz Kılma (Çalışma Zamanı)Upcasting ve Downcastinginstanceof OperatörüSoyut Sınıflar ve MetotlarÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kompozisyon vs KalıtımAgregasyon vs KompozisyonDahili, Yuvalanmış ve Anonim SınıflarEnum'lar ve Enum MetotlarıRecords (Java 16+)Sealed Classes (Java 17+)11Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıBuilder KalıbıObserver KalıbıStrategy Kalıbı14Final Meydan Okumaları
E-Öğrenme PlatformuBankacılık SistemiOyun Karakteri GeliştirmeAraç Kiralama Servisi3Sınıf Özellikleri ve Statik Üyeler
Instance ve Statik DeğişkenlerStatik MetotlarStatik BloklarSabitler (static final)Özet - Sayaç ve Utility6Arayüzler ve Soyut Sınıflar
Arayüzlere GirişArayüzleri UygulamaÇoklu Arayüz UygulamaArayüzlerde Default ve StaticSoyut Sınıflar ve ArayüzlerFonksiyonel ArayüzlerÖzet - Ödeme Sistemi9Generics
Generics'e GirişGeneric SınıflarGeneric MetotlarSınırlandırılmış Tip ParametreleriWildcard'lar (?, extends, super)Özet - Generic Container12Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit KalıbıYineleyici Kalıbı