Skip to content

Commit 3e9148c

Browse files
Template Method Pattern Added
1 parent 64de1eb commit 3e9148c

File tree

2 files changed

+280
-1
lines changed

2 files changed

+280
-1
lines changed

content/Quiz-1.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,3 @@ You are designing a **shopping cart system**.
184184
> - Each discount (percentage, flat, BOGO) can **wrap** the existing discount and add its own behavior.
185185
> - This allows stacking and combining discounts flexibly.
186186
187-
---

content/Template Method Pattern.md

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
---
2+
title: Template Method Pattern
3+
created: 2025-09-08
4+
tags:
5+
- behavioral
6+
---
7+
## Definition
8+
9+
**Template Method Pattern** defines the skeleton of an algorithm in a method, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.
10+
11+
---
12+
## Real World Analogy
13+
14+
This pattern is widely used in many frameworks and libraries. For example, **Django**, **Flask**, and **Spring** provide hooks or decorators. You simply implement a few methods and the framework handles the flow. These are perfect examples of the Template Method pattern: the framework or base class controls the overall process (request handling, lifecycle, etc.), and you supply only the specific steps.
15+
16+
Consider you want to make tea and coffee. To make either you need to:
17+
- Boil the water
18+
- Brew the coffee or tea
19+
- Pour into the cup
20+
- Add condiments
21+
22+
Class Diagram for Coffee and Tea:
23+
24+
```mermaid
25+
classDiagram
26+
class Coffee {
27+
+boilWater()
28+
+brewCoffee()
29+
+pourInCup()
30+
+addCondiments()
31+
}
32+
33+
class Tea {
34+
+boilWater()
35+
+brewTea()
36+
+pourInCup()
37+
+addCondiments()
38+
}
39+
40+
41+
```
42+
43+
The diagram shows two concrete classes, `Coffee` and `Tea`, each listing methods for steps required to prepare the beverage. In the Template Method pattern a shared base class controls the flow and subclasses provide the specific implementations for brewing and adding condiments.
44+
45+
You might ask why make separate methods when it is just an algorithm: boil → brew → pour → add condiments. Putting the common flow in an abstract base class keeps the shared algorithm in one place and lets subclasses provide only the varying steps.
46+
47+
---
48+
### Design
49+
50+
```mermaid
51+
classDiagram
52+
class CaffineBeverage {
53+
+prepareRecipe()
54+
+boilWater()
55+
+pourInCup()
56+
+brew()*
57+
+addCondiments()*
58+
}
59+
60+
class Tea {
61+
+brew()
62+
+addCondiments()
63+
}
64+
65+
class Coffee {
66+
+brew()
67+
+addCondiments()
68+
}
69+
70+
CaffineBeverage <|-- Tea
71+
CaffineBeverage <|-- Coffee
72+
73+
```
74+
75+
_Class Diagram for Template Method Pattern_
76+
This diagram highlights the abstract base class `CaffineBeverage` that defines the overall procedure (`prepareRecipe`) and the concrete subclasses `Tea` and `Coffee` that implement the varying parts (`brew()` and `addCondiments()`). The `prepareRecipe()` method is the template method that controls the sequence while delegating variable steps to subclasses.
77+
78+
---
79+
### Implementation in Java
80+
81+
Below is the implementation for creating Tea and Coffee using the Template Method Pattern.
82+
```java title="CaffineBeverage.java"
83+
abstract class CaffineBeverage {
84+
// These is our Algorithm or Say Recipe to Create the Caffine
85+
public final void prepareRecipe() {
86+
boilWater();
87+
brew();
88+
pourInCup();
89+
addCondiments();
90+
}
91+
92+
// These steps are common for Coffee and Tea
93+
public void boilWater() {
94+
System.out.println("Boiling the Water");
95+
}
96+
97+
// Common Steps for Tea and Coffee
98+
public void pourInCup() {
99+
System.out.println("Pouring in the Cup");
100+
}
101+
102+
// Sub class must provide these for creating the caffine based on what they want
103+
public abstract void brew();
104+
105+
// Sub class must provide these for creating the caffine based on what they
106+
// want.
107+
public abstract void addCondiments();
108+
}
109+
```
110+
111+
The `CaffineBeverage` class contains the fixed recipe in `prepareRecipe()` which is final so subclasses cannot change the order of steps. `boilWater()` and `pourInCup()` are implemented in the base class because they are common. `brew()` and `addCondiments()` are abstract and must be implemented by subclasses to provide beverage-specific behavior.
112+
113+
There are subclasses which implement the steps:
114+
```java title="Tea.java"
115+
// Implementation for the algorithm
116+
class Tea extends CaffineBeverage {
117+
118+
@Override
119+
public void brew() {
120+
System.out.println("Brewing Tea");
121+
}
122+
123+
@Override
124+
public void addCondiments() {
125+
System.out.println("Adding Elachi and Malai");
126+
}
127+
}
128+
129+
```
130+
131+
`Tea` implements the abstract methods with tea-specific actions. When `prepareRecipe()` runs on a `Tea` object, the base class runs the common steps and calls `Tea`'s `brew()` and `addCondiments()` at the right points.
132+
133+
```java title="Coffee.java"
134+
// Implementation for the algorithm with different calculation
135+
class Coffee extends CaffineBeverage {
136+
137+
@Override
138+
public void brew() {
139+
System.out.println("Brewing Coffee");
140+
}
141+
142+
@Override
143+
public void addCondiments() {
144+
System.out.println("Adding Extra Sugar and Milk into the Coffee");
145+
}
146+
147+
}
148+
```
149+
150+
`Coffee` provides its own versions of `brew()` and `addCondiments()`. The overall recipe from the base class is reused unchanged and only the subclass behavior differs.
151+
152+
Now Preparing the Recipe
153+
154+
```java title="TemplatePattern.java"
155+
// Calling the Algorithm
156+
CaffineBeverage mytea = new Tea();
157+
mytea.prepareRecipe();
158+
159+
System.out.println();
160+
161+
CaffineBeverage mycoffee = new Coffee();
162+
mycoffee.prepareRecipe();
163+
```
164+
165+
This code shows how client code creates concrete beverage objects and calls the single `prepareRecipe()` method. The client does not need to manage the steps; it simply invokes the template and the subclasses fill in the details.
166+
167+
**Output:**
168+
```txt
169+
Boiling the Water
170+
Brewing Tea
171+
Pouring in the Cup
172+
Adding Elachi and Malai
173+
174+
Boiling the Water
175+
Brewing Coffee
176+
Pouring in the Cup
177+
Adding Extra Sugar and Milk into the Coffee
178+
```
179+
180+
The output demonstrates the shared steps and subclass-specific steps appearing in the correct order, showing reuse of flow and customization of behavior.
181+
182+
---
183+
## Real World Example
184+
185+
In our case the real world example can be sorting a list of custom objects. You can use `ArrayList.sort()` directly for primitive or comparable types. However, for sorting non-primitive types we often implement a custom comparator and pass it to the sort method. This is similar to giving the variable part (comparison logic) to the library sorting algorithm (the template).
186+
187+
In this example we are going to sort ducks by their weight using the inbuilt sort method of **ArrayList**.
188+
```java title="CustomSort.java"
189+
package template;
190+
191+
import java.util.ArrayList;
192+
import java.util.Comparator;
193+
194+
// Custom Class/Object
195+
class Duck {
196+
private int Weight;
197+
private String Name;
198+
199+
public int getWeight() {
200+
return Weight;
201+
}
202+
203+
public String getName() {
204+
return Name;
205+
}
206+
207+
public Duck(int weight, String name) {
208+
this.Name = name;
209+
this.Weight = weight;
210+
}
211+
}
212+
213+
// Implementing the Custom Comparator for sorting
214+
class SortDuckByWeight implements Comparator<Duck> {
215+
216+
@Override
217+
public int compare(Duck o1, Duck o2) {
218+
return Integer.compare(o1.getWeight(), o2.getWeight());
219+
}
220+
221+
}
222+
223+
public class CustomSort {
224+
225+
public static void main(String[] args) {
226+
// Create the List of Duck class
227+
ArrayList<Duck> list = new ArrayList<Duck>();
228+
addInList(list, 23, "Duck23");
229+
addInList(list, 12, "Duck12");
230+
addInList(list, 34, "Duck34");
231+
System.out.println("Before Sorting");
232+
printList(list);
233+
234+
list.sort(new SortDuckByWeight());
235+
System.out.println("\nAfter Sorting");
236+
printList(list);
237+
238+
}
239+
240+
public static void addInList(ArrayList<Duck> ducks, int weight, String name) {
241+
ducks.add(new Duck(weight, name));
242+
}
243+
244+
public static void printList(ArrayList<Duck> ducks) {
245+
for (Duck duck : ducks) {
246+
System.out.println("Ducks\tWeight=" + duck.getWeight() + " Name=" + duck.getName());
247+
}
248+
}
249+
250+
}
251+
```
252+
253+
`Duck` is a simple data class with `Weight` and `Name` fields and getters. `SortDuckByWeight` implements `Comparator<Duck>` and contains the weight-based comparison. `CustomSort` builds a list, prints it, sorts it with the custom comparator, and prints the result, showing how library algorithms can be reused by providing the variable parts.
254+
255+
**Output:**
256+
```txt
257+
Before Sorting
258+
Ducks Weight=23 Name=Duck23
259+
Ducks Weight=12 Name=Duck12
260+
Ducks Weight=34 Name=Duck34
261+
262+
After Sorting
263+
Ducks Weight=12 Name=Duck12
264+
Ducks Weight=23 Name=Duck23
265+
Ducks Weight=34 Name=Duck34
266+
```
267+
268+
The before and after output shows the effect of passing a custom comparator into the standard sorting algorithm; the algorithm is reused while the comparison logic is supplied externally.
269+
270+
---
271+
## Design Principles:
272+
273+
- **Encapsulate What Varies** - Identify the parts of the code that are going to change and encapsulate them into separate class just like the Strategy Pattern.
274+
- **Favor Composition Over Inheritance** - Instead of using inheritance on extending functionality, rather use composition by delegating behavior to other objects.
275+
- **Program to Interface not Implementations** - Write code that depends on Abstractions or Interfaces rather than Concrete Classes.
276+
- **Strive for Loosely coupled design between objects that interact** - When implementing a class, avoid tightly coupled classes. Instead, use loosely coupled objects by leveraging abstractions and interfaces. This approach ensures that the class does not heavily depend on other classes.
277+
- **Classes Should be Open for Extension But closed for Modification** - Design your classes so you can extend their behavior without altering their existing, stable code.
278+
- **Depend on Abstractions, Do not depend on concrete class** - Rely on interfaces or abstract types instead of concrete classes so you can swap implementations without altering client code.
279+
- **Talk Only To Your Friends** - An object may only call methods on itself, its direct components, parameters passed in, or objects it creates.
280+
- **Don't Call us, we'll call you** - The framework/base class controls the flow and calls subclass code when needed.

0 commit comments

Comments
 (0)