<aside> đ đ Category: Structural
</aside>
Adapter pattern memungkinkan objek dengan interface yang tidak kompatibel untuk bekerja sama. Pattern ini bertindak sebagai wrapper yang menerjemahkan satu interface ke interface lain yang diharapkan oleh client.
<aside> âšī¸ Analogi: Seperti adaptor colokan listrik yang memungkinkan Anda menggunakan perangkat elektronik dari negara lain. Adaptor mengubah format colokan agar kompatibel dengan stop kontak lokal.
</aside>
Anda perlu menggunakan library atau class pihak ketiga, tetapi interface-nya tidak kompatibel dengan kode yang sudah ada. Mengubah kode existing atau library pihak ketiga sangat berisiko dan tidak praktis.
Buat adapter class yang mengimplementasikan interface yang diharapkan oleh client, dan secara internal menggunakan instance dari class yang ingin diadaptasi (adaptee). Adapter menerjemahkan panggilan dari client ke format yang dipahami adaptee.
// Target Interface - yang diharapkan client
public interface IPaymentProcessor
{
void ProcessPayment(decimal amount);
bool RefundPayment(string transactionId);
}
// Adaptee - Third-party payment library (incompatible interface)
public class StripePaymentGateway
{
public void MakeStripePayment(double amountInCents)
{
Console.WriteLine($"Processing Stripe payment: ${amountInCents / 100}");
}
public bool CreateStripeRefund(string chargeId)
{
Console.WriteLine($"Refunding Stripe charge: {chargeId}");
return true;
}
}
// Adapter - Makes StripePaymentGateway compatible with IPaymentProcessor
public class StripeAdapter : IPaymentProcessor
{
private readonly StripePaymentGateway _stripeGateway;
public StripeAdapter(StripePaymentGateway stripeGateway)
{
_stripeGateway = stripeGateway;
}
public void ProcessPayment(decimal amount)
{
// Convert dollars to cents for Stripe API
double amountInCents = (double)(amount * 100);
_stripeGateway.MakeStripePayment(amountInCents);
}
public bool RefundPayment(string transactionId)
{
return _stripeGateway.CreateStripeRefund(transactionId);
}
}
// Client Code
public class EcommerceService
{
private readonly IPaymentProcessor _paymentProcessor;
public EcommerceService(IPaymentProcessor paymentProcessor)
{
_paymentProcessor = paymentProcessor;
}
public void Checkout(decimal totalAmount)
{
_paymentProcessor.ProcessPayment(totalAmount);
}
}
// Usage
var stripeGateway = new StripePaymentGateway();
var adapter = new StripeAdapter(stripeGateway);
var service = new EcommerceService(adapter);
service.Checkout(99.99m); // Processing Stripe payment: $99.99
from abc import ABC, abstractmethod
# Target Interface
class IPaymentProcessor(ABC):
@abstractmethod
def process_payment(self, amount: float) -> None:
pass
@abstractmethod
def refund_payment(self, transaction_id: str) -> bool:
pass
# Adaptee - Third-party library
class StripePaymentGateway:
def make_stripe_payment(self, amount_in_cents: float) -> None:
print(f"Processing Stripe payment: ${amount_in_cents / 100}")
def create_stripe_refund(self, charge_id: str) -> bool:
print(f"Refunding Stripe charge: {charge_id}")
return True
# Adapter
class StripeAdapter(IPaymentProcessor):
def __init__(self, stripe_gateway: StripePaymentGateway):
self._stripe_gateway = stripe_gateway
def process_payment(self, amount: float) -> None:
amount_in_cents = amount * 100
self._stripe_gateway.make_stripe_payment(amount_in_cents)
def refund_payment(self, transaction_id: str) -> bool:
return self._stripe_gateway.create_stripe_refund(transaction_id)
# Client
class EcommerceService:
def __init__(self, payment_processor: IPaymentProcessor):
self._payment_processor = payment_processor
def checkout(self, total_amount: float) -> None:
self._payment_processor.process_payment(total_amount)
# Usage
stripe_gateway = StripePaymentGateway()
adapter = StripeAdapter(stripe_gateway)
service = EcommerceService(adapter)
service.checkout(99.99) # Processing Stripe payment: $99.99