> For the complete documentation index, see [llms.txt](https://jrp.gitbook.io/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jrp.gitbook.io/notes/design-pattern/creational-abstract-factory-pattern.md).

# Creational - Abstract Factory Pattern

Pre-requisite : Read [Creational - Factory Pattern](/notes/design-pattern/creational-factory-pattern.md)

Now, suppose, apart from `Transport`  object, there is another object called `Handler` . The handler can be `WarehouseHandler`  for Road Logistics and `PortHandler`  for Sea Logistics.

How do we implement similar to factory pattern?

<div data-with-frame="true"><figure><img src="https://1047267985-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M3Fx7a7TKGT3zMkvumq%2Fuploads%2FBdB2SZ6ElCSqF8oGL8C0%2Fimage.png?alt=media&amp;token=3532c713-9d6a-4521-bee8-c8adaced61d1" alt=""><figcaption></figcaption></figure></div>

Here,&#x20;

**Related Products**: Each factory ( `RoadLogistics` & `SeaLogistics` ) creates a **family of related objects** that work together (Truck + WarehouseHandler, Ship + PortHandler)

**Abstract Factory Pattern**: Each factory produces **multiple** **related products** specific to its logistics environment

```java
// Abstract Products - Transport and Handling
interface Transport {
    void deliver();
}

interface Handler {
    void handle();
}

// Concrete Products for Road Logistics
class Truck implements Transport {
    @Override
    public void deliver() {
        System.out.println("Delivering cargo by truck on road");
    }
}

class WarehouseHandler implements Handler {
    @Override
    public void handle() {
        System.out.println("Loading/unloading cargo at warehouse");
    }
}

// Concrete Products for Sea Logistics
class Ship implements Transport {
    @Override
    public void deliver() {
        System.out.println("Delivering cargo by ship across ocean");
    }
}

class PortHandler implements Handler {
    @Override
    public void handle() {
        System.out.println("Loading/unloading cargo at port with cranes");
    }
}

// Abstract Factory Interface
interface LogisticsFactory {
    Transport createTransport();
    Handler createHandler();
}

// Concrete Factory for Road Logistics
class RoadLogisticsFactory implements LogisticsFactory {
    @Override
    public Transport createTransport() {
        return new Truck();
    }
    
    @Override
    public Handler createHandler() {
        return new WarehouseHandler();
    }
}

// Concrete Factory for Sea Logistics
class SeaLogisticsFactory implements LogisticsFactory {
    @Override
    public Transport createTransport() {
        return new Ship();
    }
    
    @Override
    public Handler createHandler() {
        return new PortHandler();
    }
}

// Client code that uses the factory
class LogisticsCompany {
    private Transport transport;
    private Handler handler;
    
    public LogisticsCompany(LogisticsFactory factory) {
        transport = factory.createTransport();
        handler = factory.createHandler();
    }
    
    public void executeDelivery() {
        System.out.println("=== Starting Delivery ===");
        handler.handle();
        transport.deliver();
        System.out.println();
    }
}

// Demo
public class LogisticsDemo {
    public static void main(String[] args) {
        // Road Logistics
        System.out.println("Road Logistics:");
        LogisticsFactory roadFactory = new RoadLogisticsFactory();
        LogisticsCompany roadCompany = new LogisticsCompany(roadFactory);
        roadCompany.executeDelivery();
        
        // Sea Logistics
        System.out.println("Sea Logistics:");
        LogisticsFactory seaFactory = new SeaLogisticsFactory();
        LogisticsCompany seaCompany = new LogisticsCompany(seaFactory);
        seaCompany.executeDelivery();
    }
}

```

Output

```
Road Logistics:
=== Starting Delivery ===
Loading/unloading cargo at warehouse
Delivering cargo by truck on road

Sea Logistics:
=== Starting Delivery ===
Loading/unloading cargo at port with cranes
Delivering cargo by ship across ocean

```

**Advantages**

* **Isolation of concrete classes:**
  * Because a factory encapsulates the responsibility and the process of creating product objects, it isolates clients from implementation classes.
  * Clients manipulate instances through their abstract interfaces. Product class names are isolated in the implementation of the concrete factory; they do not appear in client code.
* **Promoting consistency among products:**
  * When product objects in a family are designed to work together, it’s important that an application use objects from only one family at a time. AbstractFactory makes this easy to enforce.

**Disadvantages**

* **Complexity:**
  * Abstract Factory can introduce additional complexity to the codebase.
  * Having multiple factories and abstract product interfaces may be overkill for simpler projects.
* **Rigidity with New Product Types:**
  * Suppose you want to add a third product (e.g., `TrackingDevice`) to every logistics family (`RoadLogistics`, `SeaLogistics`).
  * This means:
    * Every factory interface and every concrete factory class needs to be updated to add `createTrackingDevice()`.
    * You must implement `TrackingDevice` for every family.
  * It’s a big change that touches many classes—risking errors and making refactoring time-consuming.
* Difficult to test
  * Testing individual product objects outside the factory context may require **mock factories** or additional setup.
  * Rapid prototyping is harder because you must implement full product families even for simple use cases.

Then how to choose?

The **best solution depends on your requirements**—you don’t always need (or want) the full weight of the Abstract Factory pattern. Here are some commonly used alternatives and suggestions for different needs:

<table><thead><tr><th width="358.62109375">Use case</th><th>Best alternative</th></tr></thead><tbody><tr><td>Only one product per scenario</td><td>Simple Factory / Factory Method</td></tr><tr><td>Complicated object setup with many parameters</td><td>Builder Pattern</td></tr><tr><td>Spring or large-scale application</td><td>Dependency Injection (Spring DI)</td></tr><tr><td>Want plugins/extensions loaded at runtime</td><td>Registry-based Factory</td></tr><tr><td>Need strict families of related products</td><td>Abstract Factory</td></tr></tbody></table>
