Design Patterns - Abstract Factory (in Java)

Design Patterns - Abstract Factory (in Java)

Group all related object creation logics

Definition

This is a creational design pattern that allows you to create families of related objects without specifying their concrete classes.

Let's continue this discussion from where we left off with the Factory Method Design Pattern. So if you don’t know about the Factory Method Design Pattern please read it first from here.

Towards Abstract Factory - Step by Step

High-Level Overview

This is the Factory Method Design Pattern:

  • ClassB has multiple Implementations - ClassB1, ClassB2, …, ClassBn

  • ClassA HAS-A ClassB object

  • Factory Method Pattern says:

    • delegate ClassB subclasses object creation logic (createObjectB()) to the ClassA subclasses

Now, let’s introduce another interface ClassC and its implementations - ClassC1, ClassC2, …, ClassCn.

  • ClassA HAS-A ClassC object.

  • delegate the ClassC subclasses object creation logic (createObjectC()) to ClassA subclasses

All the new changes are marked as RED in the diagram.

That’s it, we have implemented the Abstract Factory Design Pattern.

Low-Level Design Overview

In our logistics service, we have Logistic and Transport.

We have another thing missing, that is Packaging, It could be of two types BoxPackaging & ContainerPackaging.

Now, let’s update the Logistic class, similar to Transport, Packaging is also a HAS-A relation to Logistic.

Logically BoxPackaging is related to RoadLogistic and ContainerPackaging is related to SeaLogistic.

So if we apply the Factory Method Design Pattern for the Packaging class, we need to introduce createPackaging() delegation in Logistic.

All the RED colored text are new changes.

Here, we group (or create families) road logistic-related object creation logic inside the RoadLogistic class and sea logistic-related object creation logic inside the SeaLogistic class.

Congratulations! You have successfully implemented the Abstract Factory Design Pattern.

Here is the full code:

interface Transport {
    void delivery();
}

class Truck implements Transport {
    private String name = "Truck";

    @Override
    public void delivery() {
        String message = "On road delivery by " + name;
        System.out.println(message);
    }
}

class Ship implements Transport {
    private String name = "Ship";

    @Override
    public void delivery() {
        String message = "On sear delivery by " + name;
        System.out.println(message);
    }
}

interface Packaging {
    void pack();
}

class BoxPackaging implements Packaging {
    @Override
    public void pack() {
        System.out.println("Packaging in a box");
    }
}

class ContainerPackaging implements Packaging {
    @Override
    public void pack() {
        System.out.println("Packaging in a container");
    }
}

abstract class Logistic {
    private Transport transport;
    private Packaging packaging;

    public abstract Transport createTransport();

    public abstract Packaging createPackaging();

    public void planDelivery() {
        packaging = createPackaging();
        packaging.pack();

        transport = createTransport();
        transport.delivery();
    }
}

class RoadLogistic extends Logistic {
    @Override
    public Transport createTransport() {
        return new Truck();
    }

    @Override
    public Packaging createPackaging() {
        return new BoxPackaging();
    }
}

class SeaLogistic extends Logistic {
    @Override
    public Transport createTransport() {
        return new Ship();
    }

    @Override
    public Packaging createPackaging() {
        return new ContainerPackaging();
    }
}

class FactoryMethodDemo {
    public static void main(String[] args) {
        Logistic roadLogistic = new RoadLogistic();
        roadLogistic.planDelivery();

        Logistic seaLogistic = new SeaLogistic();
        seaLogistic.planDelivery();
    }
}

Benefits of Abstract Factory

  • Grouping related object creation logic

    • improve code maintainability and modularity
  • OCP is achieved similar to factory method design pattern