Menu
CoddyTech

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.

challenge icon

Tantangan

Mudah

Mari 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 MediaPlayer dengan method virtual murni berikut:

    • play(const std::string& filename): memutar file yang ditentukan
    • stop(): menghentikan pemutaran
    • setVolume(int level): mengatur volume (0-100)

    Sertakan destructor virtual.

  • LegacyAudioLib.h: Buat library audio "legacy" yang sudah ada dengan antarmuka yang tidak kompatibel.

    Class LegacyAudioLib mewakili library lama yang bekerja secara berbeda dari yang diharapkan pemutarmu. Class ini harus memiliki:

    • loadAudio(const std::string& path): mencetak Legacy: Loading [path]
    • startPlayback(): mencetak Legacy: Playback started
    • stopPlayback(): mencetak Legacy: Playback stopped
    • adjustVolume(double percentage): menerima angka desimal (0.0 hingga 1.0) dan mencetak Legacy: Volume set to [percentage] (tampilkan nilai desimalnya)
  • AudioAdapter.h: Buat adapter yang menjembatani kedua antarmuka.

    Class AudioAdapter harus mewarisi MediaPlayer dan menyimpan referensi ke object LegacyAudioLib. Adapter menerjemahkan pemanggilan dari antarmuka modern ke antarmuka legacy:

    • play() harus memanggil loadAudio() dan startPlayback() pada library legacy
    • stop() harus mendelegasikan ke stopPlayback()
    • 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:

    1. Nama file yang akan diputar (string)
    2. Tingkat volume (bilangan bulat, 0-100)

    Buat sebuah instance LegacyAudioLib dan AudioAdapter yang membungkusnya. Lalu gunakan adapter melalui antarmuka MediaPlayer (simpan sebagai pointer MediaPlayer) untuk:

    1. Mengatur volume ke tingkat input
    2. Memutar nama file yang menjadi input
    3. Menghentikan pemutaran

Contohnya, dengan input song.mp3 dan 75:

Legacy: Volume set to 0.75
Legacy: Loading song.mp3
Legacy: Playback started
Legacy: Playback stopped

Dengan input podcast.wav dan 50:

Legacy: Volume set to 0.5
Legacy: Loading podcast.wav
Legacy: Playback started
Legacy: Playback stopped

Perhatikan 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;
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Object

Latihan sendiri: Compiler C++ online