Last Updated on September 24, 2023 by KnownSense
The Template Method is a behavioral design pattern that defines a blueprint for an algorithm in a superclass but allows specific steps of the algorithm to be overridden by subclasses without changing its core structure.
Consider developing a data mining application that analyzes corporate documents in various formats (PDF, DOC, CSV) to extract meaningful data. Initially, separate classes were created to handle each format, resulting in duplicated code. Additionally, client code had conditional statements based on the processing object’s class, leading to complexity.
This pattern involves breaking down an algorithm into steps, converting these steps into methods, and placing calls to these methods inside a template method. These steps can be either abstract or include default implementations. Clients are expected to provide their own subclasses, implement abstract steps, and optionally override non-abstract steps. This approach simplifies the code by eliminating duplication and allows for polymorphic behavior.
Another example is mass housing construction follows a template method-like approach. The architectural plan for a standard house can include extension points, enabling homeowners to customize certain aspects of their houses. Each construction step, like laying the foundation or installing plumbing, can be slightly adjusted to create unique variations while maintaining a common structure.
Benefits
UML of Template Method
Implementation
Here is the simplified example to analyze corporate documents in various formats (PDF, DOC, CSV) using the Template Method pattern.
Step1: Create DocumentProcessor which is the abstract template class defining the template method processDocument and abstract steps for opening, extracting data, analyzing data, generating a report, and closing the document.
abstract class DocumentProcessor {
public void processDocument(String filePath) {
openDocument(filePath);
List<String> data = extractData(filePath);
analyzeData(data);
generateReport(data);
closeDocument();
}
protected abstract void openDocument(String filePath);
protected abstract List<String> extractData(String filePath);
protected abstract void analyzeData(List<String> data);
protected abstract void generateReport(List<String> data);
protected abstract void closeDocument();
}
Step2: Create concrete subclasses for processing PDF, DOC and CSV documents, providing specific implementations for each step.
class PdfDocumentProcessor extends DocumentProcessor {
@Override
protected void openDocument(String filePath) {
System.out.println("Opening PDF document: " + filePath);
// Add PDF-specific logic here
}
@Override
protected List<String> extractData(String filePath) {
System.out.println("Extracting data from PDF document: " + filePath);
// Add PDF data extraction logic here
return List.of("PDF Data 1", "PDF Data 2");
}
@Override
protected void analyzeData(List<String> data) {
System.out.println("Analyzing PDF data");
// Add PDF data analysis logic here
}
@Override
protected void generateReport(List<String> data) {
System.out.println("Generating PDF report");
// Add PDF report generation logic here
}
@Override
protected void closeDocument() {
System.out.println("Closing PDF document");
// Add PDF-specific closing logic here
}
}
class DocDocumentProcessor extends DocumentProcessor {
@Override
protected void openDocument(String filePath) {
System.out.println("Opening DOC document: " + filePath);
// Add DOC-specific logic here
}
@Override
protected List<String> extractData(String filePath) {
System.out.println("Extracting data from DOC document: " + filePath);
// Add DOC data extraction logic here
return List.of("DOC Data 1", "DOC Data 2");
}
@Override
protected void analyzeData(List<String> data) {
System.out.println("Analyzing DOC data");
// Add DOC data analysis logic here
}
@Override
protected void generateReport(List<String> data) {
System.out.println("Generating DOC report");
// Add DOC report generation logic here
}
@Override
protected void closeDocument() {
System.out.println("Closing DOC document");
// Add DOC-specific closing logic here
}
}
class CsvDocumentProcessor extends DocumentProcessor {
@Override
protected void openDocument(String filePath) {
System.out.println("Opening CSV document: " + filePath);
// Add CSV-specific logic here
}
@Override
protected List<String> extractData(String filePath) {
System.out.println("Extracting data from CSV document: " + filePath);
// Add CSV data extraction logic here
return List.of("CSV Data 1", "CSV Data 2");
}
@Override
protected void analyzeData(List<String> data) {
System.out.println("Analyzing CSV data");
// Add CSV data analysis logic here
}
@Override
protected void generateReport(List<String> data) {
System.out.println("Generating CSV report");
// Add CSV report generation logic here
}
@Override
protected void closeDocument() {
System.out.println("Closing CSV document");
// Add CSV-specific closing logic here
}
}
Step3: In the main method, you can create instances of the appropriate document processors and call the processDocument
method to analyze corporate documents in various formats using the template method pattern.
public class DocumentProcessingApp {
public static void main(String[] args) {
DocumentProcessor pdfProcessor = new PdfDocumentProcessor();
pdfProcessor.processDocument("sample.pdf");
DocumentProcessor docProcessor = new DocDocumentProcessor();
docProcessor.processDocument("sample.doc");
DocumentProcessor csvProcessor = new CsvDocumentProcessor();
csvProcessor.processDocument("sample.csv");
}
}
OUTPUT:
Opening PDF document: sample.pdf
Extracting data from PDF document: sample.pdf
Analyzing PDF data
Generating PDF report
Closing PDF document
Opening DOC document: sample.doc
Extracting data from DOC document: sample.doc
Analyzing DOC data
Generating DOC report
Closing DOC document
Opening CSV document: sample.csv
Extracting data from CSV document: sample.csv
Analyzing CSV data
Generating CSV report
Closing CSV document
Conclusion
The Template Method pattern provides a framework for defining the structure of an algorithm while allowing flexibility in implementing specific steps by subclasses. It promotes code reusability by encapsulating common behavior in a template method and enables customization through method overriding. This pattern enhances code organization, reduces duplication, and simplifies maintenance in situations where different variations of an algorithm share a common structure.