Pola Adapter
Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan C++ di Coddy. Pelajaran 97 dari 104.
Pola Adapter memungkinkan interface yang tidak kompatibel bekerja bersama. Pola ini bertindak sebagai jembatan antara dua class, mengubah interface salah satu class menjadi interface yang diharapkan client. Pola ini sangat berguna saat mengintegrasikan kode lama atau library pihak ketiga yang tidak sesuai dengan interface sistemmu.
Bayangkan kamu memiliki class yang sudah ada dan melakukan hal yang kamu butuhkan, tetapi antarmukanya tidak sesuai dengan yang diharapkan kodemu. Alih-alih mengubah salah satu sisi, kamu membuat adapter yang membungkus class yang sudah ada dan menerjemahkan pemanggilan:
#include <iostream>
#include <string>
// class yang sudah ada dengan antarmuka yang tidak kompatibel
class LegacyPrinter {
public:
void printMessage(const std::string& msg) {
std::cout << "Legacy: " << msg << "\n";
}
};
// Antarmuka target yang diharapkan client
class Printer {
public:
virtual void print(const std::string& text) = 0;
virtual ~Printer() = default;
};
// Adapter membungkus LegacyPrinter dan mengimplementasikan antarmuka Printer
class PrinterAdapter : public Printer {
LegacyPrinter& legacy;
public:
PrinterAdapter(LegacyPrinter& lp) : legacy(lp) {}
void print(const std::string& text) override {
legacy.printMessage(text); // Sesuaikan pemanggilan
}
};
int main() {
LegacyPrinter oldPrinter;
PrinterAdapter adapter(oldPrinter);
// client menggunakan antarmuka yang diharapkan
adapter.print("Hello World");
}Adapter menyimpan referensi ke LegacyPrinter dan mengimplementasikan antarmuka Printer. Saat print() dipanggil, adapter meneruskan panggilan ke printMessage(). Kode client bekerja dengan antarmuka Printer tanpa mengetahui implementasi lama yang ada di baliknya.
Gunakan Adapter saat kamu ingin menggunakan class yang sudah ada, tetapi interfacenya tidak sesuai dengan kebutuhanmu, atau saat kamu perlu membuat class yang dapat digunakan kembali dan bekerja sama dengan class yang memiliki interface yang tidak kompatibel.
Tantangan
MudahMari buat sistem Media Player Adapter yang menjembatani berbagai antarmuka library audio. Bayangkan kamu mengintegrasikan library audio lama ke dalam aplikasi pemutar media modern: library lama berfungsi dengan sempurna, tetapi antarmukanya tidak sesuai dengan yang diharapkan pemutarmu. Di sinilah pola Adapter sangat berguna.
Kamu akan mengatur kodemu dalam empat file:
MediaPlayer.h: Definisikan antarmuka target yang diharapkan pemutar media modernmu.Buat class abstrak
MediaPlayerdengan method virtual murni berikut:play(const std::string& filename): memutar file yang ditentukanstop(): menghentikan pemutaransetVolume(int level): mengatur volume (0-100)
Sertakan destructor virtual.
LegacyAudioLib.h: Buat library audio "legacy" yang sudah ada dengan antarmuka yang tidak kompatibel.Class
LegacyAudioLibmewakili library lama yang bekerja secara berbeda dari yang diharapkan pemutarmu. Class ini harus memiliki:loadAudio(const std::string& path): mencetakLegacy: Loading [path]startPlayback(): mencetakLegacy: Playback startedstopPlayback(): mencetakLegacy: Playback stoppedadjustVolume(double percentage): menerima angka desimal (0.0 hingga 1.0) dan mencetakLegacy: Volume set to [percentage](tampilkan nilai desimalnya)
AudioAdapter.h: Buat adapter yang menjembatani kedua antarmuka.Class
AudioAdapterharus mewarisiMediaPlayerdan menyimpan referensi ke objectLegacyAudioLib. Adapter menerjemahkan pemanggilan dari antarmuka modern ke antarmuka legacy:play()harus memanggilloadAudio()danstartPlayback()pada library legacystop()harus mendelegasikan kestopPlayback()setVolume()menerima bilangan bulat (0-100), tetapi library legacy mengharapkan angka desimal (0.0-1.0), jadi kamu perlu mengonversinya
main.cpp: Tunjukkan cara kerja adapter.Baca dua input:
- Nama file yang akan diputar (string)
- Tingkat volume (bilangan bulat, 0-100)
Buat sebuah instance
LegacyAudioLibdanAudioAdapteryang membungkusnya. Lalu gunakan adapter melalui antarmukaMediaPlayer(simpan sebagai pointerMediaPlayer) untuk:- Mengatur volume ke tingkat input
- Memutar nama file yang menjadi input
- Menghentikan pemutaran
Contohnya, dengan input song.mp3 dan 75:
Legacy: Volume set to 0.75
Legacy: Loading song.mp3
Legacy: Playback started
Legacy: Playback stoppedDengan input podcast.wav dan 50:
Legacy: Volume set to 0.5
Legacy: Loading podcast.wav
Legacy: Playback started
Legacy: Playback stoppedPerhatikan bahwa kode client sepenuhnya menggunakan antarmuka MediaPlayer. Kode tersebut tidak mengetahui bahwa library legacy yang melakukan pekerjaan sebenarnya di balik layar. Adapter menangani semua penerjemahan, termasuk mengonversi volume bilangan bulat menjadi angka desimal. Inilah inti pola Adapter: membuat antarmuka yang tidak kompatibel dapat bekerja bersama tanpa mengubah kedua sisi.
Coba sendiri
#include <iostream>
#include <string>
#include "MediaPlayer.h"
#include "LegacyAudioLib.h"
#include "AudioAdapter.h"
using namespace std;
int main() {
// Baca input
string filename;
int volumeLevel;
cin >> filename;
cin >> volumeLevel;
// TODO: Buat instance LegacyAudioLib
// TODO: Buat AudioAdapter yang membungkus library lama
// TODO: Simpan adapter sebagai pointer MediaPlayer
// TODO: Gunakan antarmuka MediaPlayer untuk:
// 1. Atur volume ke tingkat input
// 2. Putar file dari input
// 3. Hentikan pemutaran
return 0;
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Object
1Dasar-Dasar OOP
File EksternalBuild dan Kompilasi C++File Header dan File SourceNamespace dan CakupanPengantar OOP dalam C++class vs objectPointer 'this'method (Fungsi Anggota)Atribut (Anggota Data)Dasar Ctor dan DtorRingkasan: Kalkulator Sederhana4Properti class
Anggota instance vs staticGetter dan setterFungsi anggota constKata kunci mutableMethod dan variabel staticFungsi dan class friendRangkuman, Pengelola Rekening Bank7Pewarisan
Pewarisan DasarTingkat Akses pada PewarisanUrutan Pemanggilan Ctor & DtorPenimpaan methodFungsi Virtual & VTablePewarisan BergandaPewarisan VirtualRangkuman: Hierarki Karyawan2Manajemen Memori
Memori Stack vs HeapPointer dan ReferenceMemori Dinamis (new/delete)Smart Pointer di C++RAII di C++Rangkuman: Pengelola Array Dinamis5Enkapsulasi
Penentu Akses dalam C++Penentu Akses secara MendalamPenyembunyian Informasistruct vs classNested dan Inner classRangkuman, Sistem Catatan Siswa8Polimorfisme
Polimorfisme saat Compile vs RuntimeOverloading FungsiMeninjau Kembali Fungsi VirtualFungsi Virtual MurniKelas AbstrakDesain Interface di C++Casting Dinamis & RTTIRangkuman: Kalkulator Bentuk11Konsep OOP Lanjutan
Komposisi vs PewarisanMixin melalui CRTPIdiom PimplPenghapusan TipeKelas Enum dan Pengetikan KuatPenanganan Pengecualian dalam OOPHierarki Pengecualian Kustom14Pola Desain Bagian 2
Pola CommandPola AdapterPola DecoratorPola Template MethodPola StatePola CompositeRAII sebagai Pola3Konstruktor & Destruktor
Konstruktor DefaultKonstruktor BerparameterKonstruktor SalinKonstruktor PindahDaftar Inisialisasi KonstruktorKonstruktor DelegasiKupas Tuntas DestruktorAturan Tiga, Lima, dan NolRangkuman: class String6Overloading Operator
Pengantar Overloading OperatorOverloading Operator AritmetikaOverloading Operator PerbandinganOperator StreamOverloading Operator PenugasanOverloading Operator [] dan ()Operator Konversi TipeRingkasan, class Matrix9Template
Template FungsiTemplate classSpesialisasi TemplateTemplate VariadikDasar SFINAE & Type TraitsRangkuman, Container GenerikLatihan sendiri: Compiler C++ online