Table of contents
Introduction
The Factory Design Pattern is a creational design pattern that provides a way to create objects without specifying their exact class or creating the objects directly. Instead, a factory class is responsible for creating objects of the desired type based on certain conditions, parameters, or configurations.
Why Factory Design Pattern?
The main advantage of using the Factory Design Pattern is that it provides a centralized location for object creation, making it easier to manage and modify the creation process without affecting the rest of the code. It also makes the code more flexible and extensible, allowing you to add new types of objects without changing the existing code.
The factory class can be designed in many different ways, depending on the specific requirements of the application. Here are some common patterns for implementing the factory class:
Common patterns
Simple Factory: The factory class has a single method that takes a parameter and returns an object of the desired type. This method can be static or non-static, depending on the requirements of the application.
Factory Method: The factory class defines an abstract method that creates objects of the desired type. Subclasses of the factory class implement this method to create specific types of objects.
Abstract Factory: The factory class defines a set of abstract methods that create objects of different types. Subclasses of the factory class implement these methods to create specific families of related objects.
Now that we understand the basic concepts of the Factory Design Pattern, let's look at some examples to see how it works in practice.
Example: Simple Factory
Suppose we are developing a pizza ordering system that allows customers to order different types of pizzas. We want to use the Factory Design Pattern to create pizza objects dynamically based on the customer's order.
Example
// Pizza class hierarchy
abstract class Pizza {
String name;
String dough;
String sauce;
List<String> toppings = new ArrayList<>();
void prepare() {
System.out.println("Preparing " + name);
System.out.println("Tossing " + dough + " dough");
System.out.println("Adding " + sauce + " sauce");
System.out.println("Adding toppings:");
for (String topping : toppings) {
System.out.println(" " + topping);
}
}
void bake() {
System.out.println("Baking pizza for 25 minutes at 350 degrees");
}
void cut() {
System.out.println("Cutting pizza into diagonal slices");
}
void box() {
System.out.println("Placing pizza in official PizzaStore box");
}
}
class CheesePizza extends Pizza {
public CheesePizza() {
name = "Cheese Pizza";
dough = "Regular crust";
sauce = "Marinara sauce";
toppings.add("Fresh mozzarella");
toppings.add("Parmesan");
}
}
class PepperoniPizza extends Pizza {
public PepperoniPizza() {
name = "Pepperoni Pizza";
dough = "Thin crust";
sauce = "Tomato sauce";
toppings.add("Pepperoni");
toppings.add("Sausage");
toppings.add("Mushrooms");
}
}
// Pizza factory
class SimplePizzaFactory {
public Pizza createPizza(String type) {
if (type.equals("cheese")) {
return new CheesePizza();
} else if (type.equals("pepperoni")) {
return new PepperoniPizza();
} else {
throw new IllegalArgumentException("Couldn't identify the Pizza type");
}
}
}