avatarPeterson C

Summary

The website content provides a detailed guide on the Factory Method design pattern, explaining its purpose, implementation, and benefits within object-oriented software development.

Abstract

The Factory Method design pattern is presented as a creational pattern that abstracts the instantiation process of objects, allowing for the creation of objects without specifying their exact class. This pattern is part of the "Gang of Four" design patterns, which aim to create flexible, maintainable, and scalable object-oriented software. The guide illustrates the practical application of the Factory Method by simulating a bakery scenario in Java, where a PastryFactory class is used to create different types of pastries based on an enum. The pattern promotes loose coupling by decoupling the creation of objects from the system that uses the objects, adhering to the S.O.L.I.D principles of programming. The article concludes by emphasizing the importance of selecting the appropriate design pattern for the specific problem at hand and encourages readers with a call for "Happy coding."

Opinions

  • The Factory Method pattern is praised for its ability to control object creation and for providing a mechanism to extend the range of objects that can be created without changing the client code.
  • The author suggests that using interfaces to define common behaviors for classes is a good practice when dealing with multiple classes with similar behaviors.
  • The article conveys that the Factory Method pattern aligns with the S.O.L.I.D principles, which are essential for designing robust and maintainable software.
  • The author implies that the Factory Method pattern is superior to directly instantiating classes, as it provides more flexibility and scalability for software development.
  • The use of real-world analogies, such as ordering pastries at a bakery, is intended to make the concept more relatable and understandable to the reader.
  • The article encourages judicious use of design patterns, highlighting that each pattern is suited to specific problems and should be applied thoughtfully.

A guide to software design patterns

Creational Design Pattern: Factory Method

Photo by Ale Alvarez on Unsplash

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.

Photo by Viktor Forgacs on Unsplash

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

Next: Creational Design Pattern: Abstract Factory

Design Patterns
Software Development
Software Engineering
Software Architecture
Programming
Recommended from ReadMedium