Adaptör Kalıbı
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 97 / 104.
Adapter kalıbı, uyumsuz arayüzlerin birlikte çalışmasını sağlar. İki sınıf arasında köprü görevi görerek bir sınıfın arayüzünü istemcilerin beklediği arayüze dönüştürür. Bu, özellikle sisteminizin arayüzüyle uyuşmayan eski kodu veya üçüncü taraf kütüphaneleri entegre ederken kullanışlıdır.
İhtiyacınız olan işi yapan mevcut bir sınıfınız olduğunu, ancak arayüzünün kodunuzun beklediğiyle eşleşmediğini hayal edin. Taraflardan herhangi birini değiştirmek yerine, mevcut sınıfı saran ve çağrıları dönüştüren bir adaptör oluşturursunuz:
#include <iostream>
#include <string>
// Uyumsuz arayüze sahip mevcut sınıf
class LegacyPrinter {
public:
void printMessage(const std::string& msg) {
std::cout << "Legacy: " << msg << "\n";
}
};
// İstemcinin beklediği hedef arayüz
class Printer {
public:
virtual void print(const std::string& text) = 0;
virtual ~Printer() = default;
};
// Adapter, LegacyPrinter'ı sarar ve Printer arayüzünü uygular
class PrinterAdapter : public Printer {
LegacyPrinter& legacy;
public:
PrinterAdapter(LegacyPrinter& lp) : legacy(lp) {}
void print(const std::string& text) override {
legacy.printMessage(text); // Çağrıyı çevir
}
};
int main() {
LegacyPrinter oldPrinter;
PrinterAdapter adapter(oldPrinter);
// İstemci beklenen arayüzü kullanır
adapter.print("Hello World");
}Adaptör, LegacyPrinter öğesine bir referans tutar ve Printer arayüzünü uygular. print() çağrıldığında, işlemi printMessage() öğesine devreder. İstemci kodu, altında yatan eski uygulamayı bilmeden Printer arayüzüyle çalışır.
Mevcut bir sınıfı kullanmak istediğinizde ancak arabirimi ihtiyaçlarınızla eşleşmediğinde veya uyumsuz arabirimlere sahip sınıflarla birlikte çalışan yeniden kullanılabilir bir sınıf oluşturmanız gerektiğinde Adapter kullanın.
Görev
KolayFarklı ses kitaplıklarının arayüzlerini birbirine bağlayan bir Media Player Adapter sistemi oluşturalım. Eski bir ses kitaplığını modern bir medya oynatıcı uygulamasına entegre ettiğinizi düşünün: eski kitaplık kusursuz çalışıyor, ancak arayüzü oynatıcınızın beklediği arayüzle eşleşmiyor. Adapter kalıbının öne çıktığı yer tam olarak burasıdır.
Kodunuzu dört dosyaya düzenleyeceksiniz:
MediaPlayer.h: Modern medya oynatıcınızın beklediği hedef arayüzü tanımlayın.Aşağıdaki saf sanal yöntemlere sahip soyut bir
MediaPlayersınıfı oluşturun:play(const std::string& filename): belirtilen dosyayı oynatırstop(): oynatmayı durdurursetVolume(int level): ses düzeyini ayarlar (0-100)
Sanal bir yıkıcı ekleyin.
LegacyAudioLib.h: Uyumsuz bir arayüze sahip mevcut "eski" ses kitaplığını oluşturun.LegacyAudioLibsınıfınız, oynatıcınızın beklediğinden farklı çalışan eski bir kitaplığı temsil eder. Şunlara sahip olmalıdır:loadAudio(const std::string& path):Legacy: Loading [path]yazdırırstartPlayback():Legacy: Playback startedyazdırırstopPlayback():Legacy: Playback stoppedyazdırıradjustVolume(double percentage): ondalık bir değer (0.0 ile 1.0 arası) alır veLegacy: Volume set to [percentage]yazdırır (ondalık değeri gösterir)
AudioAdapter.h: İki arayüzü birbirine bağlayan adapter'ı oluşturun.AudioAdaptersınıfınızMediaPlayersınıfından kalıtım almalı ve birLegacyAudioLibnesnesine başvuru tutmalıdır. Adapter, modern arayüzden gelen çağrıları eski arayüze çevirir:play(), eski kitaplık üzerinde hemloadAudio()hem destartPlayback()yöntemlerini çağırmalıdırstop(), çağrıyıstopPlayback()yöntemine devretmelidirsetVolume()bir tamsayı (0-100) alır, ancak eski kitaplık ondalık bir değer (0.0-1.0) bekler; bu nedenle dönüştürmeniz gerekir
main.cpp: Adapter'ın çalışmasını gösterin.İki girdi okuyun:
- Oynatılacak bir dosya adı (dize)
- Bir ses düzeyi (tamsayı, 0-100)
Bir
LegacyAudioLibörneği ve onu saran birAudioAdapteroluşturun. Ardından adapter'ıMediaPlayerarayüzü üzerinden (birMediaPlayerişaretçisi olarak saklayarak) şu işlemler için kullanın:- Ses düzeyini giriş değerine ayarlayın
- Girişteki dosya adını oynatın
- Oynatmayı durdurun
Örneğin, song.mp3 ve 75 girdileriyle:
Legacy: Volume set to 0.75
Legacy: Loading song.mp3
Legacy: Playback started
Legacy: Playback stoppedpodcast.wav ve 50 girdileriyle:
Legacy: Volume set to 0.5
Legacy: Loading podcast.wav
Legacy: Playback started
Legacy: Playback stoppedİstemci kodunun tamamen MediaPlayer arayüzüyle çalıştığına dikkat edin. Altta gerçek işi bir eski kitaplığın yaptığından haberi yoktur. Adapter, tamsayı ses düzeyini ondalık değere dönüştürmek de dahil olmak üzere tüm çevirileri yönetir. Adapter kalıbının özü budur: taraflardan hiçbirini değiştirmeden uyumsuz arayüzlerin birlikte çalışmasını sağlamak.
Kendin dene
#include <iostream>
#include <string>
#include "MediaPlayer.h"
#include "LegacyAudioLib.h"
#include "AudioAdapter.h"
using namespace std;
int main() {
// Girdileri oku
string filename;
int volumeLevel;
cin >> filename;
cin >> volumeLevel;
// TODO: Bir LegacyAudioLib örneği oluştur
// TODO: Eski kütüphaneyi saran bir AudioAdapter oluştur
// TODO: Adaptörü bir MediaPlayer işaretçisi olarak sakla
// TODO: MediaPlayer arayüzünü şunlar için kullan:
// 1. Ses seviyesini girdi seviyesine ayarla
// 2. Girdi dosya adını oynat
// 3. Oynatmayı durdur
return 0;
}
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 DosyalarC++ Build ve DerlemeBaşlık Dosyaları ve Kaynak DosyalarıAd Alanları ve KapsamC++'ta OOP'ye GirişSınıflar ve Nesneler'this' İşaretçisiMetotlar (Üye Fonksiyonlar)Öznitelikler (Veri Üyeleri)Ctor ve Dtor TemelleriÖzet - Basit Hesap Makinesi4Sınıf Özellikleri
Örnek ve Statik ÜyelerGetter ve Setter MetotlarıConst Üye FonksiyonlarMutable Anahtar KelimesiStatik Metotlar ve DeğişkenlerFriend Fonksiyonlar ve SınıflarÖzet - Banka Hesabı Yöneticisi7Kalıtım
Temel KalıtımKalıtım Erişim SeviyeleriCtor ve Dtor Çağrılma SırasıMetot Geçersiz KılmaSanal Fonksiyonlar ve VTableÇoklu KalıtımSanal KalıtımÖzet - Çalışan Hiyerarşisi10STL Genel Bakış
STL Genel Bakış ve FelsefesiSTL KonteynerleriİteratörlerSTL AlgoritmalarıFunctor'lar ve Lambda İfadeleriÖzet - Kelime Frekansı13Tasarım Kalıpları 1. Bölüm
Tasarım Kalıplarına GirişSingleton KalıbıFactory ve Abstract FactoryBuilder KalıbıObserver KalıbıStrategy Kalıbı2Bellek Yönetimi
Stack ve Heap Bellekİşaretçiler ve ReferanslarDinamik Bellek (new/delete)C++'ta Akıllı İşaretçilerC++'ta RAIIÖzet - Dinamik Dizi Yöneticisi5Kapsülleme
C++'da Erişim BelirleyicilerDerinlemesine Erişim BelirleyicilerBilgi GizlemeStruct vs Classİç İçe ve Dahili SınıflarÖzet - Öğrenci Kayıt Sistemi8Çok Biçimlilik
Derleme ve Çalışma Zamanı Çok BiçimliliğiFonksiyon Aşırı YüklemeSanal Fonksiyonlara Yeniden BakışSaf Sanal FonksiyonlarSoyut SınıflarC++'ta Arayüz TasarımıDynamic Casting ve RTTIÖzet - Şekil Hesaplayıcı11İleri Düzey OOP Kavramları
Kompozisyon ve Kalıtım KarşılaştırmasıCRTP ile Mixin YapılarıPimpl İdiyomuTür Silme (Type Erasure)Enum Sınıfları ve Güçlü TiplendirmeOOP'de İstisna YönetimiÖzel İstisna Hiyerarşileri14Tasarı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ıBir Kalıp Olarak RAII3Yapıcılar ve Yıkıcılar
Varsayılan YapıcıParametreli YapıcıKopya YapıcıTaşıma YapıcısıYapıcı İlklendirme ListeleriTemsilci YapıcılarYıkıcılara Derinlemesine BakışÜç / Beş / Sıfır KuralıÖzet - String Sınıfı6Operatör Aşırı Yükleme
Operatör Aşırı Yüklemeye GirişAritmetik Operatör Aşırı YüklemeKarşılaştırma Operatörü Aşırı YüklemeStream OperatörleriAtama Operatörü Aşırı Yükleme[] ve () Operatör Aşırı YüklemeTip Dönüşüm OperatörleriÖzet - Matris Sınıfı9Şablonlar
Fonksiyon ŞablonlarıSınıf ŞablonlarıŞablon ÖzelleştirmeVariadic ŞablonlarSFINAE ve Type Traits TemelleriÖzet - Generic KonteynerKendi başına pratik yap: Online C++ derleyicisi