Adaptör Kalıbı
Coddy'nin Java Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 71 / 87.
Adapter Deseni (Adapter Pattern), uyumsuz arayüzlerin birlikte çalışmasına olanak tanıyan yapısal bir tasarım desenidir. Bir sınıfın arayüzünü istemcinin beklediği bir arayüz haline dönüştürerek iki sınıf arasında bir köprü görevi görür. Bunu, bir Avrupa cihazını Amerikan prizine takmanıza olanak tanıyan bir güç adaptörü gibi düşünebilirsiniz.
Ses dosyalarını çalan mevcut bir MediaPlayer arayüzüne sahip olduğunuzu, ancak videoları oynatmak için tamamen farklı bir arayüz kullanan üçüncü taraf bir kütüphaneyi entegre etmeniz gerektiğini hayal edin:
// Kodunuzun kullandığı mevcut arayüz
interface MediaPlayer {
void play(String filename);
}
// Uyumsuz arayüze sahip üçüncü taraf sınıf
class AdvancedVideoPlayer {
public void playVideo(String filename) {
System.out.println("Playing video: " + filename);
}
}Adaptör, uyumsuz sınıfı sarmalar ve beklenen arayüzü uygulayarak aralarındaki çağrıları dönüştürür:
class VideoPlayerAdapter implements MediaPlayer {
private AdvancedVideoPlayer videoPlayer;
public VideoPlayerAdapter() {
this.videoPlayer = new AdvancedVideoPlayer();
}
public void play(String filename) {
videoPlayer.playVideo(filename);
}
}Artık istemci kodunuz, video oynatıcıyı tanıdık MediaPlayer arayüzü aracılığıyla kullanabilir:
MediaPlayer player = new VideoPlayerAdapter();
player.play("movie.mp4"); // Çıktı: Video oynatılıyor: movie.mp4Adaptör Deseni, kaynak kodlarını değiştirmeden eski kodları veya üçüncü taraf kütüphaneleri entegre ederken paha biçilemezdir. İstemci, adapte edilmiş bir sınıfla çalıştığının farkında olmaz; sadece bildiği arayüzü kullanır.
Görev
KolayAdapter Pattern kullanarak bir sıcaklık dönüştürme sistemi inşa edelim! Elinizde Santigrat (Celsius) sıcaklıklarıyla çalışan mevcut bir hava durumu uygulaması var, ancak yalnızca Fahrenhayt cinsinden okuma yapan eski bir sıcaklık sensörünü entegre etmeniz gerekiyor. Her iki sistemi de değiştirmek yerine, aradaki boşluğu dolduran bir adaptör oluşturacaksınız.
Kodunuzu dört dosya halinde düzenleyeceksiniz:
TemperatureProvider.java: Hava durumu uygulamanızın beklediği arayüzü (interface) tanımlayın. Santigrat cinsinden sıcaklığı temsil eden bir double döndürengetTemperatureCelsius()metodunu bildirmelidir.FahrenheitSensor.java: Bu, uyumsuz bir arayüzü olan eski sensörü temsil eder. Fahrenhayt cinsinden sıcaklık için, yapıcı (constructor) aracılığıyla ayarlanan özel (private) bir double alanı olan bir sınıf oluşturun. Saklanan Fahrenhayt değerini döndüren birreadFahrenheit()metoduna sahip olmalıdır.SensorAdapter.java: Fahrenhayt sensörünü hava durumu uygulamanızla uyumlu hale getiren adaptörü oluşturun. AdaptörünüzTemperatureProviderarayüzünü uygulamalı (implement) ve birFahrenheitSensornesnesini sarmalamalıdır.getTemperatureCelsius()çağrıldığında, sensörden değeri okumalı ve şu formülü kullanarak Santigrat'a dönüştürmelidir:(fahrenheit - 32) * 5 / 9.Main.java: Her şeyi bir araya getirin! Bir girdi alacaksınız: Fahrenhayt cinsinden bir sıcaklık okuması (double).Girdi değeriyle bir
FahrenheitSensoroluşturun. Ardından bu sensörü sarmalayan birSensorAdapteroluşturun. Hava durumu uygulamanızın beklenen arayüz üzerinden bunu kullanabileceğini göstermek için adaptörü birTemperatureProviderdeğişkeninde saklayın.Sonucu şu formatta yazdırın:
Temperature: [celsius] C; burada celsius değeri virgülden sonra bir basamak olacak şekilde formatlanmalıdır.
Bir girdi alacaksınız: Fahrenhayt sıcaklığı (double).
Örneğin, 98.6 girdisi ile çıktınız şöyle olacaktır:
Temperature: 37.0 CMain sınıfınızın tamamen TemperatureProvider arayüzü ile nasıl çalıştığına dikkat edin; gerçek sıcaklığın arka planda uyarlanan bir Fahrenhayt sensöründen geldiğine dair hiçbir fikri yoktur. İşte Adapter Pattern'in zarafeti budur!
Kopya kağıdı
Adapter (Adaptör) Deseni, iki sınıf arasında bir köprü görevi görerek uyumsuz arayüzlerin birlikte çalışmasını sağlayan ve bir arayüzü istemcinin beklediği başka bir arayüze dönüştüren yapısal bir tasarım desenidir.
Temel Bileşenler
- Target Interface (Hedef Arayüz): İstemcinin kullanmayı beklediği arayüz
- Adaptee (Uyarlanan): Uyumsuz arayüze sahip olan mevcut sınıf
- Adapter (Adaptör): Hedef arayüzü uygulayan ve uyarlanan sınıfı sarmalayarak aralarındaki çağrıları dönüştüren sınıf
Temel Yapı
// Hedef arayüz
interface MediaPlayer {
void play(String filename);
}
// Adaptee (uyumsuz sınıf)
class AdvancedVideoPlayer {
public void playVideo(String filename) {
System.out.println("Playing video: " + filename);
}
}
// Adaptör
class VideoPlayerAdapter implements MediaPlayer {
private AdvancedVideoPlayer videoPlayer;
public VideoPlayerAdapter() {
this.videoPlayer = new AdvancedVideoPlayer();
}
public void play(String filename) {
videoPlayer.playVideo(filename);
}
}
// İstemci kullanımı
MediaPlayer player = new VideoPlayerAdapter();
player.play("movie.mp4"); // Çıktı: Playing video: movie.mp4Ne Zaman Kullanılır?
Adapter Deseni şu durumlarda kullanışlıdır:
- Eski kodları veya üçüncü taraf kütüphaneleri, kaynak kodlarını değiştirmeden entegre ederken
- Uyumsuz arayüzlerin birlikte çalışmasını sağlarken
- İstemcinin uyarlanan uygulamadan habersiz kalması gerektiğinde
Kendin dene
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double fahrenheit = scanner.nextDouble();
// TODO: Girdi değeriyle bir FahrenheitSensor oluşturun
// TODO: Sensörü sarmalayan bir SensorAdapter oluşturun
// TODO: Adaptörü bir TemperatureProvider değişkeninde saklayın
// TODO: Sıcaklığı Celsius cinsinden alın ve yazdırın
// Format: "Temperature: [celsius] C" bir ondalık basamakla
// İpucu: Biçimlendirme için String.format("%.1f", value) kullanı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ı