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-AClassB
objectFactory Method Pattern says:
- delegate
ClassB
subclasses object creation logic (createObjectB()
) to theClassA
subclasses
- delegate
Now, let’s introduce another interface ClassC
and its implementations - ClassC1
, ClassC2
, …, ClassCn
.
ClassA
HAS-AClassC
object.delegate the
ClassC
subclasses object creation logic (createObjectC()
) toClassA
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