# Template MethodA intermediate-level guide to Template Method: before-and-after java code and diagrams for a CS student.

## The "Copy-Paste" Problem

Imagine you are building a data processing engine. You have different file formats—like plain text and HTML—that need to be processed. While the specific way you read an HTML tag is different from how you read a line of text, the high-level workflow remains identical: you open the file, you read the content, and you complete the process.

If you implement these as separate classes without any shared structure, you end up with "Duplicate Code." This isn't just annoying; it is a significant technical debt. If you decide to add a logging step or a security check to your workflow later, you have to remember to manually update every single class. Miss one, and your application behaves inconsistently.

```java
public class TextDataProcessor {
    // Duplicate workflow logic for text files
    public void process(String filePath) {
        System.out.println("Opening file: " + filePath);
        System.out.println("Reading content from text...");
        String content = "Hello, World!"; // Simulated read
        System.out.println("Content: " + content);
    }
}

public class HtmlDataProcessor {
    // Duplicate workflow logic for HTML files
    public void process(String filePath) {
        System.out.println("Opening file: " + filePath);
        System.out.println("Reading content from HTML...");
        String content = "<h1>Hello</h1>"; // Simulated read
        System.out.println("Content: " + content); 
    }
}
```

Because `TextDataProcessor` and `HtmlDataProcessor` share no common ancestor, they are isolated islands. To a computer, their `process` methods look entirely unrelated, even though they follow the exact same sequence of events.

```mermaid
classDiagram
    class TextDataProcessor {
        +process(String filePath)
    }
    class HtmlDataProcessor {
        +process(String filePath)
    }
```

## The Intuition: A Fixed Recipe

Think of a recipe for making different types of pancakes. The "template" or the core algorithm is fixed: first you mix ingredients, then you pour them on the pan, then you flip them, and finally you serve them. 

You might change the type of flour (the implementation) or add blueberries (a specific step), but the sequence remains rigid. You wouldn't suddenly decide to serve the pancakes before mixing the batter. The Template Method pattern uses this exact logic: it defines the skeleton of an algorithm in a base class, letting subclasses redefine certain steps without changing the algorithm's structure.

## Defining the Template Method

To implement this, we use three specific Java concepts:
1. **Inheritance**: A way for one class (the subclass) to acquire the properties and methods of another (the superclass).
2. **Abstract Class**: A "blueprint" class that cannot be instantiated on its own and is designed specifically to be inherited from.
3. **Abstract Method**: A method declared in an abstract class that has no body; it serves as a placeholder that every subclass *must* implement.

In this pattern, we create a `final` method in the superclass. The keyword `final` ensures that no subclass can override this method, effectively locking the workflow sequence so it cannot be accidentally broken. We then define "hook" methods—marked as `protected abstract`—which allow subclasses to plug in their specific logic.

```mermaid
sequenceDiagram
    participant Subtype
    Subtype ->> Subtype: process(filePath)
    Note right of Subtype: The Template Method starts here
    Subtype ->> Subtype: openFile(filePath)
    Subtype ->> Subtype: readData()
    Note over Subtype: Polymorphic dispatch to subclass logic
    Subtype ->> Subtype: System.out.println("Processing complete.")
```

## From Messy to Managed

By refactoring the duplicate logic into a single base class, we centralize the workflow. The superclass `DataProcessor` now owns the "how" of the sequence, while the subclasses only care about the "what" of the specific data reading.

```java
public abstract class DataProcessor {
    // The Template Method defining the fixed workflow
    public final void process(String filePath) {
        openFile(filePath);
        readData();
        System.out.println("Processing complete.");
    }

    private void openFile(String filePath) {
        System.out.println("Opening file: " + filePath);
    }

    // Abstract steps to be implemented by subclasses
    protected abstract void readData();
}

public class TextDataProcessor extends DataProcessor {
    @Override
    protected void readData() {
        System.out.println("Reading content from text...");
        String content = "Hello, World!";
        System.out.println("Content: " + content);
    }
}

public class HtmlDataProcessor extends DataProcessor {
    @Override
    protected void readData() {
        System.out.println("Reading content from HTML...");
        String content = "<h1>Hello</h1>";
        System.out.println("Content: " + content);
    }
}
```

Now, when you want to add a new file type—say, JSON—you simply create a new subclass and implement the `readData` method. You don't have to worry about the opening or closing logic; that is already safely handled by the template.

```mermaid
classDiagram
    class DataProcessor {
        <<abstract>>
        +final process(String filePath)
        -openFile(String filePath)
        #readData()*
    }
    class TextDataProcessor {
        #readData()
    }
    class HtmlDataProcessor {
        #readData()
    }
    DataProcessor <|-- TextDataProcessor
    DataProcessor <|-- HtmlDataProcessor
```

## When to Use It, and When Not To

The Template Method is a powerful behavioral pattern, but it is not a silver bullet. 

**Use it when:**
* Multiple classes share a nearly identical algorithm structure.
* You want to control exactly which steps of an algorithm can be changed by a user (by making the template `final`).
* You want to eliminate code duplication in workflow logic.

**Avoid it when:**
* **You face "Fragile Base Class" syndrome**: If your superclass becomes too complex or changes frequently, every single subclass might break. Over-engineering the base class makes the entire hierarchy difficult to maintain.
* **You need runtime flexibility**: Template Method uses inheritance, which is a "is-a" relationship established at compile time. If you need to change the behavior of an object *while the program is running*, you should use the **Strategy** pattern (which relies on composition) instead.

## Takeaways

* Use a Template Method when you have multiple objects that follow the exact same sequence of steps but differ in one or two specific details.
* Centralize the workflow in a `final` method within an abstract superclass to prevent logic drift.
* Prefer inheritance for fixed workflows, but reach for composition (Strategy) if you need to swap behaviors dynamically at runtime.

## Usage

**Executing the template method via a subclass**

```java
DataProcessor textProc = new TextDataProcessor();
textProc.process("data.txt");
```
