The refactored code replaces hardcoded creation with a Factory-based design. The new RegionFactory interface separates the business logic from the regional classes.
1. Key Improvements
Family Consistency
The Benefit: A RegionFactory always gives you objects from one family (e.g., the India gateway and the India invoice).
The Safety: You cannot pair a US invoice with a Razorpay payment by accident, because IndiaFactory only creates Indian products.
Adherence to Open/Closed Principle (OCP)
The Benefit: To add a region (e.g., JapanFactory), write new classes that implement the existing interfaces.
The Impact: You never edit CheckoutService or the existing factories to support a new country.
Dependency Inversion
The Benefit:CheckoutService depends on abstractions (RegionFactory, PaymentGateway, Invoice), not on concrete classes (IndiaFactory, RazorpayGateway, etc.).
The Result: Changes in the low-level classes do not reach the high-level checkout logic.
2. Structural Breakdown
Component
Responsibility
Abstract Factory (RegionFactory)
The interface that lists the methods for creating each product.
Concrete Factory (IndiaFactory)
Creates the real product objects for one region.
Abstract Product (PaymentGateway)
The interface for one kind of product.
Concrete Product (PayPalGateway)
A real product that its matching concrete factory creates.
Client (CheckoutService)
Uses only the Abstract Factory and Abstract Product interfaces.
1package DesignPatterns.CreationalPatterns.AbstractFactoryDesignPattern.After;23// 1. ABSTRACT PRODUCTS: Define what we need (Payment and Invoice)4interface PaymentGateway {5 void processPayment(double amount);6}78interface Invoice {9 void generateInvoice();10}1112// 2. CONCRETE PRODUCTS: Regional implementations13class RazorpayGateway implements PaymentGateway {1415 public void processPayment(double amount) {16 System.out.println("Processing INR payment via Razorpay: " + amount);17 }18}1920class GSTInvoice implements Invoice {2122 public void generateInvoice() {23 System.out.println("Generating GST Invoice for India.");24 }25}2627class PayPalGateway implements PaymentGateway {2829 public void processPayment(double amount) {30 System.out.println("Processing USD payment via PayPal: " + amount);31 }32}3334class USInvoice implements Invoice {3536 public void generateInvoice() {37 System.out.println("Generating Invoice as per US norms.");38 }39}4041// 3. THE ABSTRACT FACTORY: An interface to create families of related objects.42// It defines 'WHAT' to create, but not 'WHICH' concrete class to use.43interface RegionFactory {44 PaymentGateway createPaymentGateway(String gatewayType);45 Invoice createInvoice();46}4748// 4. CONCRETE FACTORIES: These handle regional specifics.49// Note: These classes encapsulate the 'new' keyword and regional 'if-else' logic.50class IndiaFactory implements RegionFactory {5152 public PaymentGateway createPaymentGateway(String gatewayType) {53 if (54 gatewayType.equalsIgnoreCase("razorpay")55 ) return new RazorpayGateway();56 // Add PayU logic here...57 throw new IllegalArgumentException("Unsupported gateway for India.");58 }5960 public Invoice createInvoice() {61 return new GSTInvoice(); // Guaranteed consistency: India gets GST.62 }63}6465class USFactory implements RegionFactory {6667 public PaymentGateway createPaymentGateway(String gatewayType) {68 if (gatewayType.equalsIgnoreCase("paypal")) return new PayPalGateway();69 // Add Stripe logic here...70 throw new IllegalArgumentException("Unsupported gateway for US.");71 }7273 public Invoice createInvoice() {74 return new USInvoice(); // Guaranteed consistency: US gets USInvoice.75 }76}7778/**79 * 5. THE CLIENT: Decoupled and flexible.80 * CheckoutService no longer cares about specific regional classes.81 * It only knows about the 'RegionFactory' interface.82 */83class CheckoutService {8485 private final PaymentGateway paymentGateway;86 private final Invoice invoice;8788 // Dependency Injection: The factory is passed in, not created inside.89 public CheckoutService(RegionFactory factory, String gatewayType) {90 this.paymentGateway = factory.createPaymentGateway(gatewayType);91 this.invoice = factory.createInvoice();92 }9394 public void completeOrder(double amount) {95 paymentGateway.processPayment(amount);96 invoice.generateInvoice();97 }98}99100class Main {101102 public static void main(String[] args) {103 // We decide the "Family" (India) at the entry point of the application.104 CheckoutService indiaCheckout = new CheckoutService(105 new IndiaFactory(),106 "razorpay"107 );108 indiaCheckout.completeOrder(1999.0);109110 // Switching regions is as easy as passing a different Factory instance.111 CheckoutService usCheckout = new CheckoutService(112 new USFactory(),113 "paypal"114 );115 usCheckout.completeOrder(49.99);116 }117}118