Factory Pattern
Java Factory Pattern (CREATIONAL PATTERN)
Creates objects without specifying the exact class - delegates instantiation logic to factory methods.
Factory Pattern: Delegates object creation to factory classes, keeping client code clean and decoupled from concrete implementations.
2. When to Use?
Section titled “2. When to Use?”When object creation logic is:
- Complex
- Needs to be centralized
- Should be hidden from client
- May change frequently
3. Simple Example: Without vs With Factory
Section titled “3. Simple Example: Without vs With Factory”❌ Without Factory (Direct Instantiation)
Section titled “❌ Without Factory (Direct Instantiation)”interface Vehicle { void drive();}
class Car implements Vehicle { public void drive() { System.out.println("Driving car"); }}
class Bike implements Vehicle { public void drive() { System.out.println("Riding bike"); }}
// Problem: Client knows concrete classespublic class Client { public static void main(String[] args) { Vehicle vehicle;
String type = "car"; // From config/user input
// ❌ Client decides which class to instantiate if (type.equals("car")) { vehicle = new Car(); // Tight coupling! } else if (type.equals("bike")) { vehicle = new Bike(); // More if-else for new types } else { throw new IllegalArgumentException(); }
vehicle.drive(); }}✅ With Factory (Clean)
Section titled “✅ With Factory (Clean)”// Same Vehicle interface and classes...
// Factory class encapsulates creation logicclass VehicleFactory { public static Vehicle getVehicle(String type) { if (type.equals("car")) { return new Car(); } else if (type.equals("bike")) { return new Bike(); } throw new IllegalArgumentException(); }}
// Client codepublic class Client { public static void main(String[] args) { // ✅ Client doesn't know concrete classes Vehicle vehicle = VehicleFactory.getVehicle("car"); vehicle.drive(); // Just uses it }}4. Three Factory Variants
Section titled “4. Three Factory Variants”1. Simple Factory (Static Factory)
Section titled “1. Simple Factory (Static Factory)”// Shown above - static methodclass PizzaFactory { public static Pizza createPizza(String type) { switch(type.toLowerCase()) { case "cheese": return new CheesePizza(); case "pepperoni": return new PepperoniPizza(); default: throw new IllegalArgumentException(); } }}
// UsagePizza pizza = PizzaFactory.createPizza("cheese");2. Factory Method Pattern
Section titled “2. Factory Method Pattern”// Abstract creator with factory methodabstract class Dialog { // Factory method - subclasses implement abstract Button createButton();
void render() { Button button = createButton(); // Calls subclass method button.onClick(); button.render(); }}
// Concrete creatorsclass WindowsDialog extends Dialog { Button createButton() { return new WindowsButton(); // Creates Windows variant }}
class WebDialog extends Dialog { Button createButton() { return new HTMLButton(); // Creates Web variant }}
// UsageDialog dialog = new WindowsDialog();dialog.render(); // Creates WindowsButton3. Abstract Factory Pattern
Section titled “3. Abstract Factory Pattern”// Factory of factories - creates families of related objectsinterface GUIFactory { Button createButton(); Checkbox createCheckbox();}
// Concrete factoriesclass WindowsFactory implements GUIFactory { public Button createButton() { return new WindowsButton(); } public Checkbox createCheckbox() { return new WindowsCheckbox(); }}
class MacFactory implements GUIFactory { public Button createButton() { return new MacButton(); } public Checkbox createCheckbox() { return new MacCheckbox(); }}
// Application uses abstract factoryclass Application { private GUIFactory factory;
Application(GUIFactory factory) { this.factory = factory; }
void createUI() { Button button = factory.createButton(); Checkbox checkbox = factory.createCheckbox(); // All components match (all Windows or all Mac) }}5. Real-World Examples
Section titled “5. Real-World Examples”Example 1: Logger Factory
Section titled “Example 1: Logger Factory”interface Logger { void log(String message);}
class FileLogger implements Logger { public void log(String msg) { System.out.println("Writing to file: " + msg); }}
class DatabaseLogger implements Logger { public void log(String msg) { System.out.println("Saving to DB: " + msg); }}
class LoggerFactory { public static Logger getLogger(String type) { if (type.equals("file")) return new FileLogger(); if (type.equals("database")) return new DatabaseLogger(); if (type.equals("console")) return new ConsoleLogger(); return new ConsoleLogger(); // Default }}
// Usage in applicationLogger logger = LoggerFactory.getLogger("file");logger.log("Error occurred");Example 2: Payment Processor Factory
Section titled “Example 2: Payment Processor Factory”class PaymentFactory { public static PaymentProcessor create(String country) { switch(country) { case "US": return new StripeProcessor(); case "EU": return new PayPalProcessor(); case "IN": return new RazorpayProcessor(); default: return new DefaultProcessor(); } }}
// Client code doesn't change when adding new countriesPaymentProcessor processor = PaymentFactory.create("IN");processor.process(1000);6. Interview Q&A
Section titled “6. Interview Q&A”Q1: Factory Method vs Abstract Factory?
Section titled “Q1: Factory Method vs Abstract Factory?”A:
- Factory Method: One method creates one product
- Abstract Factory: Factory creates families of related products
Q2: Why not just use new?
Section titled “Q2: Why not just use new?”A: Because:
- Encapsulation: Creation logic hidden
- Flexibility: Easy to add new types
- Decoupling: Client doesn’t depend on concrete classes
- Single Responsibility: Creation logic in one place
Q3: When to use which factory?
Section titled “Q3: When to use which factory?”A:
- Simple Factory: Basic object creation
- Factory Method: When subclass decides which object
- Abstract Factory: When need related object families
Q4: Real example in Java/JDK?
Section titled “Q4: Real example in Java/JDK?”A:
Calendar.getInstance()- Factory methodNumberFormat.getNumberInstance()- Factory methodDocumentBuilderFactory.newInstance()- Abstract factory
Q5: Difference with Builder Pattern?
Section titled “Q5: Difference with Builder Pattern?”A:
- Factory: Creates different types of objects
- Builder: Creates complex single object with many parts
7. Spring Framework Example
Section titled “7. Spring Framework Example”// Spring uses factory pattern extensively@Componentpublic class VehicleFactory {
@Autowired private Car car;
@Autowired private Bike bike;
public Vehicle getVehicle(String type) { if ("car".equals(type)) return car; if ("bike".equals(type)) return bike; throw new IllegalArgumentException(); }}
// Usage with Dependency Injection@Servicepublic class TransportService { @Autowired private VehicleFactory factory;
public void transport(String type) { Vehicle vehicle = factory.getVehicle(type); vehicle.drive(); }}8. Implementation Template
Section titled “8. Implementation Template”// Product interfaceinterface Product { void use();}
// Concrete productsclass ConcreteProductA implements Product { public void use() { System.out.println("Using Product A"); }}
class ConcreteProductB implements Product { public void use() { System.out.println("Using Product B"); }}
// Factoryclass ProductFactory { public static Product createProduct(String type) { if ("A".equals(type)) return new ConcreteProductA(); if ("B".equals(type)) return new ConcreteProductB(); throw new IllegalArgumentException(); }}
// Clientpublic class Main { public static void main(String[] args) { Product product = ProductFactory.createProduct("A"); product.use(); }}9. Advantages
Section titled “9. Advantages”- Loose Coupling: Client doesn’t know concrete classes
- Single Responsibility: Creation logic in one place
- Open/Closed: Easy to add new types without modifying client
- Centralized Control: Easy to implement caching, pooling, etc.