WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

Design Patterns · Intermediate · question 38 of 100

Can you provide an example of combining the Template Method pattern with the Factory Method pattern for extensibility and flexibility?

📕 Buy this interview preparation book: 100 Design Patterns questions & answers — PDF + EPUB for $5

We can combine the Template Method and Factory Method design patterns to achieve flexibility and extensibility in our code. The Template Method pattern is used when we want to define the skeleton of an algorithm in base class while allowing derived classes to override some specific steps of the algorithm. The Factory Method pattern is used when we want to delegate the responsibility of creating objects to the derived classes, allowing us to create objects of different types at runtime.

Let’s say we are building a framework to process different types of documents (e.g., PDF, Word, Excel, etc.). We want to define a base class for all types of documents, while allowing derived classes to override specific steps of the document processing algorithm. Additionally, we want to be able to create different types of documents at runtime, so we will use the Factory Method pattern.

Here’s an example implementation:

public abstract class DocumentProcessor {

    // Template Method pattern
    public final void processDocument() {
        openDocument();
        readDocument();
        parseDocument();
        // Hook method
        if (shouldCompressDocument()) {
            compressDocument();
        }
        writeDocument();
        closeDocument();
    }

    private void openDocument() {
        // Default implementation
    }

    protected abstract void readDocument();

    protected abstract void parseDocument();

    // Hook method
    protected boolean shouldCompressDocument() {
        return false; // Default implementation
    }

    private void compressDocument() {
        // Default implementation
    }

    protected abstract void writeDocument();

    private void closeDocument() {
        // Default implementation
    }
    
    // Factory Method pattern
    public static DocumentProcessor createDocumentProcessor(String documentType) {
        switch (documentType) {
            case "PDF":
                return new PdfDocumentProcessor();
            case "Word":
                return new WordDocumentProcessor();
            case "Excel":
                return new ExcelDocumentProcessor();
            // Add cases for other document types here
            default:
                throw new IllegalArgumentException("Invalid document type: " + documentType);
        }
    }
}

public class PdfDocumentProcessor extends DocumentProcessor {
    protected void readDocument() {
        // Implementation for reading a PDF document
    }

    protected void parseDocument() {
        // Implementation for parsing a PDF document
    }

    protected void writeDocument() {
        // Implementation for writing a PDF document
    }
}

public class WordDocumentProcessor extends DocumentProcessor {
    protected void readDocument() {
        // Implementation for reading a Word document
    }

    protected void parseDocument() {
        // Implementation for parsing a Word document
    }

    protected void writeDocument() {
        // Implementation for writing a Word document
    }
}

public class ExcelDocumentProcessor extends DocumentProcessor {
    protected void readDocument() {
        // Implementation for reading an Excel document
    }

    protected void parseDocument() {
        // Implementation for parsing an Excel document
    }

    protected void writeDocument() {
        // Implementation for writing an Excel document
    }

    // Override Hook method
    protected boolean shouldCompressDocument() {
        return true;
    }
}

In this example, we have defined a ‘DocumentProcessor‘ base class that implements the document processing algorithm using the Template Method pattern. The ‘openDocument()‘, ‘compressDocument()‘, and ‘closeDocument()‘ methods have default implementations, while the ‘readDocument()‘, ‘parseDocument()‘, and ‘writeDocument()‘ methods are abstract and must be implemented by derived classes.

We have also defined a ‘shouldCompressDocument()‘ hook method that can be optionally overridden by derived classes to modify the behavior of the algorithm. In the ‘ExcelDocumentProcessor‘ class, we have overridden this hook method to enable document compression.

Finally, we have created a ‘createDocumentProcessor()‘ factory method in the ‘DocumentProcessor‘ class that returns an instance of a specific document processor based on the provided document type. This method can be extended to add support for additional document types.

Using this implementation, we can create different types of document processors at runtime:

DocumentProcessor pdfProcessor = DocumentProcessor.createDocumentProcessor("PDF");
pdfProcessor.processDocument();

DocumentProcessor wordProcessor = DocumentProcessor.createDocumentProcessor("Word");
wordProcessor.processDocument();

DocumentProcessor excelProcessor = DocumentProcessor.createDocumentProcessor("Excel");
excelProcessor.processDocument();

This provides us with the flexibility and extensibility we need, as we can add new document types and override specific steps of the document processing algorithm as needed.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic Design Patterns interview — then scores it.
📞 Practice Design Patterns — free 15 min
📕 Buy this interview preparation book: 100 Design Patterns questions & answers — PDF + EPUB for $5

All 100 Design Patterns questions · All topics