A guide to software design patterns
Creational Design Pattern: Factory Method
The factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without specifying the exact class of the object to be created. This is accomplished by creating objects by calling a factory method — either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes — rather than by calling a constructor.
In plain English, that simply means you call a factory and pass one parameter and a class is created for you without having to instantiate the class yourself. The factory takes care of all that internally for you. You just need to know which value to pass for each distinct class you want to create. In our case, we’ll create a factory and show how to use it to create objects.
This pattern is also one of the “Gang of Four” design patterns that describe how to solve recurring design problems to design flexible and reusable object-oriented software, that is, objects that are easier to implement, maintain, test, reuse, and scale. It also adheres to the S.O.L.I.D principles of programming by decoupling the construction of objects from the objects themselves.
Let’s say you work for a company that makes delicious treats. You’re tasked to create a package that allows its consumers to create four types of pastries, which are: Baklava, CinnamonRoll, Flaky, and Puff. I’m sure your company will make way more pastries soon, but we’ll start with these four for now.
Now at first, If the first thing that comes to mind is to create a class for each type of pastry, that would be a way of doing it. However, this way would create more problems than it solves in the long run. Whenever you’re dealing with multiple classes with similar behaviors, it’s good practice to start with an interface that defines these behaviors and have your classes implement that interface. Your high-level modules now can make use of your interface instead of being tightly coupled to the concrete implementation of your classes.
Because we’re baking pastries, we want to be in control of how we bake each pastry and only provide a finished product to consumers. For instance, when someone goes to a bakery, they have no clue about all the ingredients and the instructions followed to bake pastries, they just order them by name or pointing to them. We’re essentially aiming for the same thing with our factory. We want to just create and return an instance of a class when someone calls our factory and provide us with a parameter that specifies which type of pastry they want.
That is exactly what the factory method does. In this case, it allows us to control how each type of pastry is created. I’m going to create a PastryFactory class to simulate our bakery using the factory method pattern in java. It should be similar in other OOP languages as well.
Let’s start with an interface since we’re going to be making pastry. We’ll name our interface Pastry. We’ll only have one method to our interface and named getFirstTimeImpression, which only returns a string of my impression of each of these treats.
public interface Pastry {
String getFirstTimeImpression();
}We start with an interface to decouple our high-level modules from being dependent on low-level modules. Now let’s create an enum with the four types of pastries we’ll be creating in our factory. We’ll call it PastryType.
public enum PastryType {
Puff,
Baklava,
Flaky,
CinnamonRoll
}Now let’s create the concrete class for each of the supported enums and have each class implement the Pastry interface.
//Puff
public class Puff implements Pastry {
Puff(){} @Override
public String getFirstTimeImpression() {
return "Puff is so so.";
}
}//Baklava
public class Baklava implements Pastry { Baklava(){} @Override
public String getFirstTimeImpression() {
return "Baklava is good but a bit too sweet for me.";
}
}//Flaky
public class Flaky implements Pastry {
Flaky(){} @Override
public String getFirstTimeImpression() {
return "Flaky is really good specially while still warm.";
}
}//CinnamonRoll
public class CinnamonRoll implements Pastry {
CinnamonRoll(){} @Override
public String getFirstTimeImpression() {
return "CinnamonRoll is one of my favorite pastries.";
}
}Now let’s create our factory method.
public class PastryFactory {
public static Pastry GetPastry(PastryType type){
switch (type){
case Puff:
return new Puff(); case Baklava:
return new Baklava(); case Flaky:
return new Flaky(); case CinnamonRoll:
return new CinnamonRoll(); default:
//throw exception for unsupported PastryType here...
}
}
}The code to use your factory would look like this.
Pastry baklava = PastryFactory.CreateInstance(PastryType.Baklava);
Pastry cinnamonRoll = PastryFactory.CreateInstance(PastryType.CinnamonRoll);
Pastry puff = PastryFactory.CreateInstance(PastryType.Puff);
Pastry flaky = PastryFactory.CreateInstance(PastryType.Flaky);System.out.println(baklava.getFirstTimeImpression());
System.out.println(cinnamonRoll.getFirstTimeImpression());
System.out.println(puff.getFirstTimeImpression());
System.out.println(flaky.getFirstTimeImpression());//------------------OUTPUT------------------
Baklava is good but a bit too sweet for me.
CinnamonRoll is one of my favorite pastries.
Puff is so so.
Flaky is really good specially while still warm.Remember each pattern solves a specific type of problem. You can’t use this pattern for every problem. Use your best judgment and use this when it makes sense and is the best solution.
Thank you for making it to the end. Happy coding.
Previous: Creational Design Pattern: Singleton





