cv.cm

Pemrograman · Pola desain

Penjelasan pola Proxy beserta contohnya

5 menit baca

Jawaban singkat

Proxy adalah pola desain struktural yang menyediakan objek pengganti dengan interface yang sama seperti objek asli, sehingga proxy dapat mengontrol akses ke objek asli itu. Klien berbicara dengan proxy seolah-olah itu objek aslinya, dan proxy menentukan kapan serta bagaimana meneruskan setiap panggilan. Jenis yang umum adalah virtual proxy (pembuatan lazy), protection proxy (pemeriksaan akses), caching proxy, dan remote proxy.

Tujuan dan masalah yang diselesaikan

Tujuan: menyediakan pengganti atau placeholder bagi objek lain untuk mengontrol akses ke objek tersebut. Proxy adalah salah satu pola struktural dalam buku Gang of Four (GoF).

Misalkan sebuah aplikasi memanggil layanan cuaca lewat jaringan. Setiap panggilan memakan ratusan milidetik dan berbiaya, sementara kota yang sama sering diminta berkali-kali per menit. Anda tidak bisa mengubah class layanan itu, dan Anda tidak ingin menambahkan kode caching di setiap tempat yang memanggilnya. Proxy menyelesaikan hal ini: ia mengimplementasikan interface yang sama, menyimpan cache, dan hanya memanggil layanan asli saat cache tidak berisi data. Pemanggil tidak perlu berubah sama sekali.

Gagasan yang sama mencakup kebutuhan lain: membuat objek yang mahal hanya saat pertama kali dipakai, memeriksa izin sebelum panggilan, mencatat setiap panggilan, atau menyembunyikan fakta bahwa objek aslinya berada di mesin lain.

Struktur dan peserta

PeranTanggung jawab
SubjectInterface yang dipakai bersama oleh objek asli dan proxy, sehingga klien bisa memakai salah satunya
Real subjectObjek yang melakukan pekerjaan sebenarnya
ProxyMengimplementasikan interface subject, menyimpan atau membuat referensi ke real subject, dan menambahkan logika kontrol sebelum atau sesudah meneruskan panggilan
ClientHanya bekerja dengan interface subject dan tidak tahu apakah ia memegang proxy
Jenis proxyApa yang dikontrol
Virtual proxyMenunda pembuatan objek yang mahal sampai objek itu dibutuhkan
Protection proxyMemeriksa apakah pemanggil diizinkan menjalankan suatu operasi
Caching proxyMenyimpan hasil dan mengembalikannya untuk permintaan yang berulang
Remote proxyMewakili objek di proses atau mesin lain dan menangani komunikasinya
Logging proxyMencatat panggilan dan argumen tanpa mengubah objek asli

Implementasi TypeScript: caching proxy

WeatherService adalah subject. CachedWeatherService adalah proxy: ia punya method yang sama dan hanya meneruskan ke layanan asli saat nilai di cache tidak ada atau sudah terlalu lama.

interface WeatherService {
  getTemperature(city: string): Promise<number>;
}
class RemoteWeatherService implements WeatherService {
  calls = 0;
  async getTemperature(city: string): Promise<number> {
    this.calls++; // imagine a slow HTTP request here
    return city.length * 3;
  }
}
class CachedWeatherService implements WeatherService {
  private cache = new Map<string, { value: number; time: number }>();
  constructor(private real: WeatherService, private maxAgeMs = 60_000) {}
  async getTemperature(city: string): Promise<number> {
    const hit = this.cache.get(city);
    if (hit && Date.now() - hit.time < this.maxAgeMs) return hit.value;
    const value = await this.real.getTemperature(city);
    this.cache.set(city, { value, time: Date.now() });
    return value;
  }
}
async function main() {
  const real = new RemoteWeatherService();
  const weather: WeatherService = new CachedWeatherService(real);
  await weather.getTemperature("Paris");
  await weather.getTemperature("Paris");
  console.log(await weather.getTemperature("Hanoi"), "real calls:", real.calls);
  // 15 real calls: 2
}
main();

Variabel client bertipe WeatherService, jadi Anda bisa berganti antara layanan asli dan proxy di satu tempat saja, misalnya dalam konfigurasi dependency injection.

Virtual dan protection proxy dengan JavaScript Proxy

JavaScript punya objek Proxy bawaan (ES2015) yang mencegat operasi seperti pembacaan properti, penulisan, dan pemanggilan fungsi lewat fungsi handler yang disebut trap. Ini cara praktis untuk membuat proxy tanpa menulis class untuk setiap interface.

type Account = { owner: string; balance: number };
function readOnly<T extends object>(target: T): T {
  return new Proxy(target, {
    set(_obj, prop) {
      throw new Error("Cannot change " + String(prop) + ": read-only");
    },
  });
}
const account = readOnly<Account>({ owner: "Ana", balance: 100 });
console.log(account.balance); // 100
try {
  account.balance = 0;
} catch (e) {
  console.log((e as Error).message); // Cannot change balance: read-only
}

Kapan dipakai dan kapan tidak

  • Pakai untuk menambahkan lazy loading, kontrol akses, caching, logging, atau akses jarak jauh tanpa mengubah class asli maupun pemanggilnya.
  • Pakai bila objek aslinya di luar kendali Anda, seperti class dari library atau klien jaringan.
  • Jangan dipakai bila pembungkus fungsi biasa sudah cukup. Untuk satu fungsi, higher-order function seperti memoize(fn) lebih sederhana daripada sebuah class.
  • Jangan menyembunyikan panggilan jarak jauh yang lambat atau gagal di balik proxy yang tampak lokal. Pemanggil tetap perlu menangani latensi dan error, jadi buat itu terlihat di interface (misalnya dengan mengembalikan Promise).
  • Hati-hati dengan identitas: proxy adalah objek yang berbeda dari real subject, sehingga proxy === real bernilai false.

Penggunaan di dunia nyata

  • Vue 3 membangun sistem reaktivitasnya di atas Proxy JavaScript: membaca properti mencatat dependensi dan menulisnya memicu pembaruan.
  • Java menyediakan java.lang.reflect.Proxy untuk membuat class proxy dinamis saat runtime; framework memakainya untuk menambahkan transaksi, pemeriksaan keamanan, atau panggilan jarak jauh di sekitar interface.
  • Object-relational mapper seperti Hibernate mengembalikan lazy proxy untuk entitas terkait dan memuat data aslinya dari database saat pertama kali diakses.
  • Library remote procedure call membuat client stub yang tampak seperti objek lokal tetapi mengirim setiap panggilan lewat jaringan.

Pola terkait

PolaPerbedaannya dengan Proxy
DecoratorStruktur sama, tujuan berbeda: Decorator menambahkan perilaku baru dan sering ditumpuk; Proxy mengontrol akses dan biasanya mengelola siklus hidup objek aslinya.
AdapterAdapter memberi objek interface yang berbeda; Proxy mempertahankan interface yang persis sama.
FacadeFacade menawarkan interface baru yang lebih sederhana untuk seluruh subsistem; Proxy menggantikan satu objek.
FlyweightFlyweight membagi objek untuk menghemat memori; virtual proxy menunda pembuatan objek untuk menghemat waktu dan memori.

FAQ

Apa perbedaan antara Proxy dan Decorator?

Keduanya membungkus objek dengan interface yang sama. Decorator menambahkan tanggung jawab dan biasanya disusun oleh klien, sedangkan proxy mengontrol akses ke objek asli dan sering membuat atau mengelola objek itu sendiri.

Apakah objek Proxy JavaScript sama dengan pola Proxy?

Itu fitur bahasa yang membuat pola ini mudah diimplementasikan. Proxy JavaScript mencegat operasi pada objek target lewat trap, persis seperti yang dilakukan proxy dalam pengertian GoF.

Apa itu virtual proxy?

Virtual proxy menggantikan objek yang mahal untuk dibuat, seperti gambar besar. Ia membuat objek asli hanya saat method yang membutuhkannya pertama kali dipanggil.

Apakah reverse proxy server contoh pola Proxy?

Gagasannya sama di level jaringan: server seperti nginx berada di depan server lain dengan interface HTTP yang sama dan menambahkan caching, kontrol akses, atau load balancing. Pola GoF menjelaskan gagasan yang sama untuk objek dalam satu program.

Semua tutorial pemrograman