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 ..

Adapter Design Pattern


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);
    }
}