Adaptör Kalıbı
Coddy'nin C# Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 57 / 70.
Adapter deseni, uyumsuz arayüzlerin birlikte çalışmasını sağlayan yapısal bir desendir. Bir sınıfın arayüzünü, istemcilerin beklediği bir arayüze 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.
Bu desen, mevcut bir sınıfı kullanmak istediğinizde ancak sınıfın arayüzü kodunuzun ihtiyaç duyduğu şeyle eşleşmediğinde özellikle yararlıdır. Orijinal sınıfı değiştirmek yerine (ki bu sınıf üzerinde kontrolünüz olmayabilir), onu sarmalayan bir adaptör oluşturursunuz:
// Uyumsuz arayüze sahip mevcut sınıf
public class OldPrinter
{
public void PrintMessage(string msg) => Console.WriteLine($"Old: {msg}");
}
// Kodunuzun beklediği arayüz
public interface IPrinter
{
void Print(string text);
}
// Adaptör aradaki boşluğu doldurur
public class PrinterAdapter : IPrinter
{
private OldPrinter _oldPrinter;
public PrinterAdapter(OldPrinter oldPrinter)
{
_oldPrinter = oldPrinter;
}
public void Print(string text)
{
_oldPrinter.PrintMessage(text); // Eski arayüze delege eder
}
}Artık kodunuz, beklenen arayüz aracılığıyla eski yazıcıyla çalışabilir:
OldPrinter legacy = new OldPrinter();
IPrinter printer = new PrinterAdapter(legacy);
printer.Print("Hello"); // Eski: HelloAdapter deseni, üçüncü taraf kütüphaneleri veya eski kodları uygulamanıza entegre ederken paha biçilemezdir. İstemci kodu, arka planda eski ve uyumsuz bir sınıfın asıl işi yaptığından tamamen habersiz bir şekilde IPrinter arayüzü ile çalışır.
Görev
KolayAdapter desenini kullanarak bir medya oynatıcı sistemi oluşturalım. MP3 dosyalarını oynatan mevcut bir ses kütüphaneniz var, ancak uygulamanızın farklı medya türlerini işleyebilen birleşik bir arayüze ihtiyacı var. Modern medya oynatıcınızın eski ses kütüphanesiyle sorunsuz çalışmasını sağlamak için bu boşluğu dolduracak bir adaptör oluşturacaksınız.
Kodunuzu üç dosya halinde düzenleyeceksiniz:
LegacyAudio.cs: Bu, değiştiremeyeceğiniz mevcut bir kütüphaneyi temsil eder.MediaSystemad alanında (namespace),"Playing MP3: {filename}"dizesini döndürenPlayMp3(string filename)metoduna sahip birLegacyAudioPlayersınıfı oluşturun. Bu sizin "adaptee"nizdir - yani uyumsuz arayüze sahip olan sınıf.MediaAdapter.cs: Arayüzü ve adaptörü aynı ad alanında oluşturun. Bir dize döndürenPlay(string filename)metoduna sahip birIMediaPlayerarayüzü tanımlayın. ArdındanIMediaPlayerarayüzünü uygulayan birMediaPlayerAdaptersınıfı oluşturun. Adaptörünüz birLegacyAudioPlayerörneğini sarmalamalı (yapıcı metot - constructor aracılığıyla iletilir) vePlayçağrısını eski oynatıcınınPlayMp3metoduna çevirmelidir.Program.cs: Eski oynatıcıyı oluşturup adaptörünüzle sarmalayarak ve adaptörüIMediaPlayerarayüzü üzerinden kullanarak her şeyi bir araya getirin. Bu, istemci kodunun modern arayüzle nasıl çalışabildiğini, adaptörün ise arka planda eski sistemle iletişimi nasıl yönettiğini gösterir.
Bir girdi alacaksınız:
- Oynatılacak dosya adı (örneğin,
song.mp3)
Bir LegacyAudioPlayer oluşturun, bunu bir MediaPlayerAdapter içine sarmalayın, ardından IMediaPlayer arayüzünü kullanarak adaptör üzerinde Play metodunu çağırın ve sonucu yazdırın.
Örneğin, girdi favorite_track.mp3 ise, çıktı şu şekilde olmalıdır:
Playing MP3: favorite_track.mp3Bu desenin güzelliği, ana kodunuzun yalnızca IMediaPlayer ile etkileşime girmesidir; asıl işi eski bir ses kütüphanesinin yaptığından haberi bile yoktur. Daha sonra farklı bir eski kütüphaneyi desteklemeniz gerekirse, istemci kodunu değiştirmeden sadece yeni bir adaptör oluşturmanız yeterli olacaktır!
Kopya kağıdı
Adapter deseni (Adapter pattern), iki sınıf arasında bir köprü görevi görerek uyumsuz arayüzlerin birlikte çalışmasını sağlayan yapısal bir desendir.
Bu desen, bir sınıfın arayüzünü istemcilerin beklediği bir arayüze dönüştürür; mevcut bir sınıfı kullanmak istediğinizde ancak arayüzü kodunuzun ihtiyaçlarıyla eşleşmediğinde kullanışlıdır.
Temel yapı:
// Uyumsuz arayüzü olan mevcut sınıf (Adaptee)
public class OldPrinter
{
public void PrintMessage(string msg) => Console.WriteLine($"Old: {msg}");
}
// Kodunuzun beklediği hedef arayüz
public interface IPrinter
{
void Print(string text);
}
// Adapter aradaki boşluğu doldurur
public class PrinterAdapter : IPrinter
{
private OldPrinter _oldPrinter;
public PrinterAdapter(OldPrinter oldPrinter)
{
_oldPrinter = oldPrinter;
}
public void Print(string text)
{
_oldPrinter.PrintMessage(text); // Eski arayüze delege eder
}
}Kullanım:
OldPrinter legacy = new OldPrinter();
IPrinter printer = new PrinterAdapter(legacy);
printer.Print("Hello"); // Old: Helloİstemci kodu, arka planda uyumsuz bir sınıfın asıl işi yaptığından habersiz bir şekilde hedef arayüzle çalışır. Bu desen, özellikle üçüncü taraf kütüphaneleri veya eski kodları entegre ederken değerlidir.
Kendin dene
using System;
using MediaSystem;
class Program
{
public static void Main(string[] args)
{
// Dosya adı girişini oku
string filename = Console.ReadLine();
// TODO: Bir LegacyAudioPlayer örneği oluşturun
// TODO: Bunu bir MediaPlayerAdapter içine sarın
// TODO: Adaptörü IMediaPlayer arayüzü üzerinden kullanın
// ve filename ile Play metodunu çağırmanın sonucunu 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 Dosyalarİsim Alanları ve YönergelerSınıf ve Nesnelere Giriş'this' Anahtar KelimesiMetotlar ve ParametrelerAlanlar ve ÖzelliklerYapıcı MetotlarNesne BaşlatıcılarÖzet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtım (:) Sözdizimi'base' Anahtar KelimesiVirtual ve Override Anahtar KelimeleriSealed Sınıflar'object' Temel SınıfıÖzet - Çalışan Hiyerarşisi7İleri Düzey Özellikler
Operatör Aşırı Yüklemeİndeksleyiciler (this[])ToString() Geçersiz KılmaGenişletme MetotlarıÖzet - Özel Liste10Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişThread-Safe SingletonFactory KalıbıObserver Kalıbı (Olaylar)Strategy Kalıbı2Özellikler ve Statik Üyeler
Otomatik Uygulanan ÖzelliklerSadece Okunur/Yazılır ÖzelliklerStatik Alanlar ve MetotlarStatik Sınıflarİfade Gövdeli Üyeler5Polimorfizm ve Arayüzler
Derleme vs Çalışma Zamanı PolimorfizmiArayüz vs Soyut SınıfÇoklu ArayüzlerBelirgin ArayüzlerUpcasting ve DowncastingÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kalıtım yerine KompozisyonGenerics (Sınıflar ve Metotlar)Delegates ve EventlerAttributes ve ReflectionIDisposable ve using İfadesiDependency Injection Temelleri11Tasarı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ı3Sınıf Mimarisi
Örnek vs Statik Veri'readonly' ve 'const' Anahtar KelimeleriDestekleyici Alanlar (Backing Fields)Özet - Banka Hesabı Yöneticisi6Kapsülleme
Erişim BelirleyicilerKapsülleme için ÖzelliklerVeri Gizleme UygulamasıDeğişmezlik KalıplarıÖzet - Öğrenci Kayıtları