In this post, we'll see how we can use an enum to implement a simple factory.
The factory design pattern is one of the most commonly used design pattern. Its various variants like simple factory, factory method and abstract factory helps you write code that follows high level of abstraction, keeping the low level details (like instantiation, object reuse, etc.) hidden from the client code.
When implementing simple factory, the idea is to provide details of the required class to be instantiated and the factory class will take care of the rest. The input details should be sufficient for the factory class to uniquely identify the class type to be instantiated.
Consider the following example:
// define the root level parent
interface Vehicle{
void drive();
}
// car - a vehicle type
class Car implements Vehicle{
@Override
public void drive() {
System.out.println("driving a car");
}
}
// truck - another vehicle
class Truck implements Vehicle{
@Override
public void drive() {
System.out.println("driving a truck");
}
}
In its simplest form, the factory for such a setup can be defined (mostly as a singleton class or a collection of static utility methods) using a bunch of if-else
or switch
statements like the one mentioned below:
class VehicleFactory{
private VehicleFactory(){
}
public static Vehicle createVehicle(String vehicleName){
if("Car".equalsIgnoreCase(vehicleName)){
return new Car();
} else if("Truck".equalsIgnoreCase(vehicleName)){
return new Truck();
}else {
throw new IllegalArgumentException("not a valid vehicle name");
}
}
}
But there are a few issues with such an implementation. The most noticeable one, is the use of if-else
or switch
statements to identify the target type. As the number of potential target types increase, so will the number of if-else
branches.
But thanks to enums
, there is a more clean way to implement the above mentioned requirement and get identical results:
public enum VehicleFactory {
Car {
@Override
public Vehicle createVehicle() {
return new Car();
}
},
Truck {
@Override
public Vehicle createVehicle() {
return new Truck();
}
};
public abstract Vehicle createVehicle();
}
// the vehicles can be instantiated using the following code:
Vehicle car = VehicleFactory.Car.createVehicle();
Vehicle truck = VehicleFactory.Truck.createVehicle();
As we can see, the enum
based factory provides a more clean way to implement factory providers for various types. The public abstract method createVehicle
is overridden in the actual enum types to instantiate the corresponding class. Moreover, enums
being inherently singleton, also makes sure that only a unique factory exists for a specific type in the runtime environment.
Another benefit with this implementation is that there are no chances of a missed provider for any type which could be the case when using if-else
or switch
blocks.
Be notified of new posts. Subscribe to the RSS feed.