Skip to content

Commit 34782d2

Browse files
Factory Method Pattern Blog
1 parent 6e8a273 commit 34782d2

File tree

2 files changed

+256
-3
lines changed

2 files changed

+256
-3
lines changed

content/Factory Method Pattern.md

+252
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
---
2+
title: Design Patterns
3+
created: 2025-04-10
4+
tags:
5+
- creational
6+
---
7+
## Definition
8+
9+
The **Factory Method Pattern** defines an interface for creating an object but allows subclasses to decide which class to instantiate. In other words, it lets a class defer instantiation to its subclasses. This pattern helps in promoting loose coupling, encapsulating object creation, and enabling easier scalability when new types are added.
10+
11+
---
12+
## Real-World Analogy
13+
14+
Imagine you have a **PizzaStore**. Popular pizza chains like Domino's or Pizza Hut have standardized processes so that anyone can order a pizza without knowing the details of its preparation. In our analogy, the pizza creation process is abstracted so that different stores can offer their own varieties of pizza.
15+
16+
Initially, you might have a base `Pizza` class with properties like name, dough, and sauce, and standard methods for preparing, baking, cutting, and boxing the pizza. Various concrete pizza classes (such as `NyStyleCheesePizza` and `ChicagoStylePaneerPizza`) extend this base class. The `PizzaStore` uses these classes to fulfill customer orders.
17+
18+
However, as your pizza business expands, you may introduce new pizza types and different styles across various stores. Rather than updating one monolithic method to handle all these variations, the Factory Method Pattern enables each store (or subclass) to decide which pizza types to create. This approach decouples the client code (the order processing) from the creation of the concrete pizza objects.
19+
20+
---
21+
## Initial Implementation
22+
23+
Below is an example of the initial design using a single `PizzaStore` class that handles different pizza types through conditional statements in the `createPizza` method:
24+
```java title="Pizza.java"
25+
abstract class Pizza {
26+
public String name;
27+
public String dough;
28+
public String sauce;
29+
30+
// Prepares the pizza by printing the preparation message
31+
public void prepare() {
32+
System.out.println(this.name + " is being prepared.");
33+
}
34+
35+
// Bakes the pizza by printing the baking message
36+
public void bake() {
37+
System.out.println("Pizza is baking.");
38+
}
39+
40+
// Cuts the pizza by printing the cutting message
41+
public void cut() {
42+
System.out.println("Pizza has been cut.");
43+
}
44+
45+
// Boxes the pizza by printing the boxing message
46+
public void box() {
47+
System.out.println("Pizza is boxed and ready for delivery.");
48+
}
49+
}
50+
```
51+
52+
For example, you might create specialized pizza classes like these:
53+
```java title="NyStyleCheesePizza.java"
54+
class NyStyleCheesePizza extends Pizza {
55+
public NyStyleCheesePizza() {
56+
this.name = "NY Style Cheese Pizza";
57+
this.dough = "NY Style Dough";
58+
this.sauce = "NY Style Sauce";
59+
}
60+
}
61+
```
62+
63+
```java title="ChicagoStylePaneerPizza.java"
64+
class ChicagoStylePaneerPizza extends Pizza {
65+
public ChicagoStylePaneerPizza() {
66+
this.name = "Chicago Paneer Pizza";
67+
this.dough = "Chicago Special Paneer Dough";
68+
this.sauce = "Chicago Homemade Sauce";
69+
}
70+
}
71+
```
72+
And the initial `PizzaStore` might be implemented as:
73+
```java title="PizzaStore.java"
74+
class PizzaStore {
75+
76+
// Processes the order by creating the pizza and performing standard steps
77+
public void orderPizza(String type) {
78+
Pizza pizza = createPizza(type);
79+
if (pizza != null) {
80+
pizza.prepare();
81+
pizza.bake();
82+
pizza.cut();
83+
pizza.box();
84+
} else {
85+
System.out.println("Sorry, we do not have that type of pizza.");
86+
}
87+
}
88+
89+
// Selects the Pizza based on the type provided
90+
public Pizza createPizza(String type) {
91+
if (type.equalsIgnoreCase("cheese")) {
92+
return new NyStyleCheesePizza();
93+
} else if (type.equalsIgnoreCase("paneer")) {
94+
return new ChicagoStylePaneerPizza();
95+
}
96+
return null;
97+
}
98+
}
99+
```
100+
**Problem:**
101+
This approach forces you to modify the `createPizza` method whenever you add new pizza types. It also makes it difficult to accommodate differing pizza styles across various stores, since the pizza creation logic is centralized rather than distributed among specialized stores.
102+
103+
---
104+
## Applying the Factory Method Pattern
105+
106+
To overcome these issues, we modify `PizzaStore` into an **abstract class**, deferring the decision of which pizza to create to its subclasses. This enables each store to have its own implementation of the `createPizza` method and supply its unique pizza offerings.
107+
### Revised Design
108+
The design diagram for the Factory Method pattern can be outlined as follows:
109+
110+
```mermaid
111+
classDiagram
112+
%% Base Pizza Class
113+
class Pizza {
114+
<<abstract>>
115+
+String name
116+
+String dough
117+
+String sauce
118+
+prepare()
119+
+bake()
120+
+cut()
121+
+box()
122+
}
123+
124+
%% New York Style Pizzas
125+
class NyStyleCheesePizza {
126+
+NyStyleCheesePizza()
127+
}
128+
class NyStyleMayoPizza {
129+
+NyStyleMayoPizza()
130+
}
131+
132+
%% Chicago Style Pizzas
133+
class ChicagostyleSchezwanPizza {
134+
+ChicagostyleSchezwanPizza()
135+
}
136+
class ChicagoStylePaneerPizza {
137+
+ChicagoStylePaneerPizza()
138+
}
139+
Pizza <|-- NyStyleCheesePizza
140+
Pizza <|-- NyStyleMayoPizza
141+
Pizza <|-- ChicagostyleSchezwanPizza
142+
Pizza <|-- ChicagoStylePaneerPizza
143+
```
144+
145+
```mermaid
146+
classDiagram
147+
%% Abstract Pizza Store
148+
class PizzaStore {
149+
<<abstract>>
150+
+orderPizza(String type)
151+
+createPizza(String type)
152+
}
153+
154+
class NyPizzaStore {
155+
+createPizza(String type)
156+
}
157+
158+
class ChicagoPizzaStore {
159+
+createPizza(String type)
160+
}
161+
162+
PizzaStore <|-- NyPizzaStore
163+
PizzaStore <|-- ChicagoPizzaStore
164+
```
165+
### Implementing the Revised Pattern
166+
167+
1. **Abstract PizzaStore Class:**
168+
The abstract class `PizzaStore` defines the common process (`orderPizza`) and declares the abstract `createPizza` method. Each subclass will implement the creation logic specific to its style.
169+
```java title="PizzaStore.java"
170+
abstract class PizzaStore {
171+
172+
// Processes the order by creating the pizza and performing the standard steps
173+
public void orderPizza(String type) {
174+
Pizza pizza = createPizza(type);
175+
if (pizza != null) {
176+
pizza.prepare();
177+
pizza.bake();
178+
pizza.cut();
179+
pizza.box();
180+
} else {
181+
System.out.println("Sorry, we do not have that type of pizza.");
182+
}
183+
}
184+
185+
// Abstract method for creating a pizza of a given type
186+
abstract public Pizza createPizza(String type);
187+
}
188+
```
189+
190+
2. **New York Pizza Store:**
191+
The `NyPizzaStore` subclass implements `createPizza` by supplying New York style pizzas.
192+
```java title="NyPizzaStore.java"
193+
// Pizza store for New York style pizzas.
194+
class NyPizzaStore extends PizzaStore {
195+
@Override
196+
public Pizza createPizza(String type) {
197+
if (type.equalsIgnoreCase("cheese")) {
198+
return new NyStyleCheesePizza();
199+
} else if (type.equalsIgnoreCase("mayonnaise")) {
200+
return new NyStyleMayoPizza();
201+
}
202+
return null;
203+
}
204+
}
205+
```
206+
207+
3. **Chicago Pizza Store:**
208+
The `ChicagoPizzaStore` subclass implements `createPizza` for Chicago style pizzas.
209+
```java title="ChicagoPizzaStore.java"
210+
// Pizza store for Chicago style pizzas.
211+
class ChicagoPizzaStore extends PizzaStore {
212+
@Override
213+
public Pizza createPizza(String type) {
214+
if (type.equalsIgnoreCase("schezwan")) {
215+
return new ChicagostyleSchezwanPizza();
216+
} else if (type.equalsIgnoreCase("paneer")) {
217+
return new ChicagoStylePaneerPizza();
218+
}
219+
return null;
220+
}
221+
}
222+
```
223+
224+
4. **Main Class to Demonstrate the Pattern:**
225+
The following code snippet shows how the client code interacts with these stores without knowing the details of pizza creation.
226+
```java title="FactoryMethod.java"
227+
public class FactoryMethod {
228+
public static void main(String[] args) {
229+
// Ordering the cheese pizza from the New York Pizza Store
230+
PizzaStore nyPizzaStore = new NyPizzaStore();
231+
nyPizzaStore.orderPizza("cheese");
232+
233+
// Ordering the paneer pizza from the Chicago Pizza Store
234+
PizzaStore chicagoStore = new ChicagoPizzaStore();
235+
chicagoStore.orderPizza("paneer");
236+
}
237+
}
238+
```
239+
**Output:**
240+
```
241+
NY Style Cheese Pizza is being prepared.
242+
Pizza is baking.
243+
Pizza has been cut.
244+
Pizza is boxed and ready for delivery.
245+
246+
Chicago Paneer Pizza is being prepared.
247+
Pizza is baking.
248+
Pizza has been cut.
249+
Pizza is boxed and ready for delivery.
250+
```
251+
---
252+
Next, we will discuss the Abstract Factory Pattern.

content/index.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ created: 2025-02-07
77
**Design patterns** are typical solutions to commonly occurring problems in software design. They are like pre-made blueprints that you can customize to solve a recurring design problem in your code.
88
## Three Main Patterns
99

10-
- **Creational patterns** provide object creation mechanisms that increase flexibility and reuse of existing code.
11-
- **Structural patterns** explain how to assemble objects and classes into larger structures, while keeping these structures flexible and efficient.
12-
- **Behavioral patterns** take care of effective communication and the assignment of responsibilities between objects.
10+
- **Creational patterns** provide object creation mechanisms that increase flexibility and reuse of existing code.
11+
- **Structural patterns** explain how to assemble objects and classes into larger structures, while keeping these structures flexible and efficient. #structural
12+
- **Behavioral patterns** take care of effective communication and the assignment of responsibilities between objects. #behavioral
1313

1414
> [!Important] Prerequisite
1515
>Must have knowledge of **OOPS (Object-Oriented Programming Principles)** and **Java**. The design patterns are primarily based on OOPS concepts. The code in this tutorial is mainly written in Java and related frameworks.
@@ -120,6 +120,7 @@ Consider an `SQLManager` class that performs CRUD operations. It has an `ILogger
120120
1. [[Strategy Pattern]]
121121
2. [[Observer Pattern]]
122122
3. [[Decorator Pattern]]
123+
4. [[Factory Method Pattern]]
123124

124125
---
125126
> [!Note]

0 commit comments

Comments
 (0)