Facebook Pixel

Template Method

Fixing a duplicated workflow

A reporting service generates two kinds of reports: CSV and JSON. Each begins by querying the database, then formats the rows, then writes output to a file. The query and write steps are identical; only the formatting differs. Without a shared structure, two nearly parallel implementations grow side by side:

1# Bad: two report classes with duplicated connect, query, and write logic.
2class CsvReportGenerator:
3    def generate(self, query: str, path: str) -> None:
4        conn = Database.connect()           # duplicated
5        rows = conn.execute(query)          # duplicated
6        with open(path, "w") as f:
7            f.write(",".join(rows[0].keys()) + "\n")
8            for row in rows:
9                f.write(",".join(str(v) for v in row.values()) + "\n")
10        conn.close()                        # duplicated
11
12class JsonReportGenerator:
13    def generate(self, query: str, path: str) -> None:
14        import json
15        conn = Database.connect()           # duplicated
16        rows = conn.execute(query)          # duplicated
17        with open(path, "w") as f:
18            json.dump([dict(r) for r in rows], f, indent=2)
19        conn.close()                        # duplicated

When a third format (XML, Parquet) is needed, the pattern repeats: copy the class, change the formatting block, copy the bugs in the connect and write logic too. The failure mode is duplicated intent, not just repeated lines: a bug in the connection-handling code must be fixed in every format class independently.

The Template Method pattern addresses this by moving the invariant steps into a base class and leaving only the varying steps to subclasses.

How it works

A base class defines the template method — a method that calls the steps of the algorithm in a fixed order. Invariant steps are implemented directly in the base class. Variable steps are declared abstract; each subclass provides its own implementation. The template method itself is not overridden — in Python by convention, in Java by marking it final.


generate() is the template method. It calls connect(), execute(), format(), and write() in order. connect(), execute(), and write() are invariant steps in the base class. format() is the abstract hook — each subclass overrides exactly that one method and nothing else.

Good: one base class fixes the skeleton, subclasses fill in the varying step

Invest in Yourself
Your new job is waiting. 83% of people that complete the program get a job offer. Unlock unlimited access to all content and features.
Go Pro