Dezign Patterns
Adapter Design Pattern
The Adapter Design Pattern is a structural design pattern that allows objects with incompatible interfaces to work together. It's like a "translator" between classes so they can interact without changing their existing code.
Intent
To convert the interface of a class into another interface that clients expect. It enables classes to work together that couldn’t otherwise because of incompatible interfaces.
Participants:
- Target: The interface expected by the client.
- Adaptee: The existing class with a different interface.
- Adapter: A wrapper that implements the Target interface and internally uses the Adaptee.
- Client : Uses the target interface
In the below code snippet , we are generating invoices from different market places like Amazon , Flipkart,..
Invoice service knows about Invoice[invoiceId,customerName,amount] . So Invoice service uses the MarketplaceInvoiceAdapter to covert the response[FlipkartInvoiceDetails or AmazonInvoiceDetails] from market places to InvoiceService compatible format i.e [Invoice].
Target : MarketplaceInvoiceAdapter
Adaptee : FlipkartService, AmazonService ...
Adapter : FlipkartInvoiceAdapter, AmazonInvoiceAdapter ...
Client : InvoiceService ..
public class Invoice {
private String invoiceId;
private String customerName;
private double amount;
public Invoice(String invoiceId, String customerName, double amount) {
this.invoiceId = invoiceId;
this.customerName = customerName;
this.amount = amount;
}
@Override
public String toString() {
return "Invoice{id='" + invoiceId + "', customer='" + customerName + "', amount=" + amount + "}";
}
}
public interface MarketplaceInvoiceAdapter {
String getMarketplaceName();
Invoice fetchInvoice();
}
@Service
public class FlipkartService {
public FlipkartInvoiceDetails fetchInvoice() {
return new FlipkartInvoiceDetails("FK789", "Alice", 850.5);
}
}
public class FlipkartInvoiceDetails {
public String code;
public String buyer;
public double value;
public FlipkartInvoiceDetails(String code, String buyer, double value) {
this.code = code;
this.buyer = buyer;
this.value = value;
}
}
@Component
public class FlipkartInvoiceAdapter implements MarketplaceInvoiceAdapter {
@Autowired
private FlipkartService service;
@Override
public String getMarketplaceName() {
return "flipkart";
}
@Override
public Invoice fetchInvoice() {
FlipkartInvoiceDetails details = service.fetchInvoice();
return new Invoice(details.code, details.buyer, details.value);
}
}
@Service
public class AmazonService {
public FlipkartInvoiceDetails fetchInvoice() {
return new FlipkartInvoiceDetails("FK789", "Alice", 850.5);
}
}
public class AmazonInvoiceDetails {
public String number;
public String customer_name;
public double amount;
public FlipkartInvoiceDetails(String number, String customer_name, double amount) {
this.number = number;
this.customer_name = customer_name;
this.amount = amount;
}
}
@Component
public class AmazonInvoiceAdapter implements MarketplaceInvoiceAdapter {
@Autowired
private AmazonService service;
@Override
public String getMarketplaceName() {
return "amazon";
}
@Override
public Invoice fetchInvoice() {
AmazonInvoiceDetails details = service.fetchInvoice();
return new Invoice(details.number, details.customer_name, details.amount);
}
}
@Component
public class MarketplaceAdapterRegistry {
private final Map<String, MarketplaceInvoiceAdapter> registry = new HashMap<>();
public MarketplaceAdapterRegistry(List<MarketplaceInvoiceAdapter> adapters) {
for (MarketplaceInvoiceAdapter adapter : adapters) {
registry.put(adapter.getMarketplaceName().toLowerCase(), adapter);
}
}
public MarketplaceInvoiceAdapter getAdapter(String marketplace) {
return registry.get(marketplace.toLowerCase());
}
}
@Service
public class InvoiceService {
@Autowired
private MarketplaceAdapterRegistry adapterRegistry;
public Invoice processInvoice(String marketplace) {
MarketplaceInvoiceAdapter adapter = adapterRegistry.getAdapter(marketplace);
if (adapter == null) {
throw new IllegalArgumentException("No adapter found for: " + marketplace);
}
return adapter.fetchInvoice();
}
}
// Client Code
@SpringBootApplication
public class InvoiceApplication implements CommandLineRunner {
@Autowired
private InvoiceService invoiceService;
public static void main(String[] args) {
SpringApplication.run(InvoiceApplication.class, args);
}
@Override
public void run(String... args) {
Invoice amazon = invoiceService.processInvoice("amazon");
Invoice flipkart = invoiceService.processInvoice("flipkart");
System.out.println(amazon);
System.out.println(myntra);
System.out.println(flipkart);
}
}