Skip to main content

Template Method Pattern: Don't Call Us, We'll Call You!


So far, the Template Method has been my most used design pattern. That is the reason why this post is quite long. J

Definition from Wiki

The Template Method defines the program skeleton of an algorithm in a method, deferring some steps to subclasses. It lets one redefine certain steps of an algorithm without changing the algorithm's structure.

Template Method UML.svg

A Real World Use Case

Imagine that you have many different kinds of documents. You want to generate a pdf file from a corresponding word template. Each type has its own small modifications but the main process for document generating is the same.

We apply the Template Method for this case. We define a final method including some steps (such as preparing for content, generating file) at a superclass. There are three possibilities for these steps at subclasses:
  1. Must be overridden: abstract methods.
  2. Not mandatory to be overridden: default protected methods.
  3. Can not be overridden: default private methods.
abstract class AbstractDocumentGenerator{
//THIS IS TEMPLATE METHOD
public final File generate() {
Document defaultDocument = prepareDocumentByDefault();
Document refinedDocument = redefineDocument(defaultDocument);
String templatePath = getTemplatePath();
String outputName = getOutputName();
return DocFactory.generate(refinedDocument, templatePath, outputName);
}
//This method is implemented at this class, can not be overridden
private Document prepareDocumentByDefault() {
Document document = new Document();
//TODO: prepare default here
return document;
}
//This is hook/default method which can be overridden by subclasses
protected Document redefineDocument(Document defaultDocument) {
return defaultDocument;
}
//These method must be implemented by subclass
protected abstract String getOutputName();
protected abstract String getTemplatePath();
}
class PaymentRequestDocumentGenerator extends AbstractDocumentGenerator {
@Override
protected String getOutputName() {
return "payment_request.pdf";
}
@Override
protected String getTemplatePath() {
return "/home/document_template/payment_request.docx";
}
}
class StandingOrderDocumentGenerator extends AbstractDocumentGenerator {
@Override
protected String getOutputName() {
return "standing_order.pdf";
}
@Override
protected String getTemplatePath() {
return "/home/document_template/standing_order.docx";
}
//Override the default method
@Override
protected Document redefineDocument(Document defaultDocument) {
defaultDocument.setDescription("Overriden the default");
return defaultDocument;
}
}

Dissecting the Pattern

Simply, we can see the following attributes:
  • Superclass has a "template" method which should be final to prevent subclasses from reworking the algorithm.
  • The template method defines the sequence of steps, each represented by a method.
  • Some methods are handled by the superclass.
  • Some methods are handled by subclasses.

Benefit? Why?

  • Reuse, avoiding duplication, and subclasses just need to implement a couple of methods.
  • The algorithm lives in one place and code changes only need to be made there.

Hooked on Template Method

A hook is a method that is declared in the abstract class but only given an empty or default implementation. This gives subclasses the ability to "hook into" the algorithm at various points if they wish; a subclass is also free to ignore the hook.

The Hollywood Principle

We allow low-level components to hooking themselves into a system, but high-level components determine when they are needed, and how. In other words, the high-level components give the low-level components a "don't call us, we'll call you" treatment.

Template Method & Strategy: Inheritance vs. Delegation

Template Method and Strategy both solve the problem of separating a generic algorithm from a detailed context. They can often be used interchangeably. However, Template Method uses inheritance to solve the problem, whereas Strategy uses composition/delegation.

Inheritance was a highlight feature in the early days of OO. That is, given some class that did something almost useful to us, we could create a subclass and change only the bits we didn't like. However, inheritance was very easy to overuse; that is a reason why we have heard of a lot of "Favor object composition over class inheritance". That is, inheritance is a very strong relationship. Derivatives are inextricably bound to their base classes. Anyway, that doesn't mean we should avoid using inheritance.

The Strategy provides one extra benefit over the Template Method. Whereas the Template Method allows a generic algorithm to manipulate many possible detailed implementations, the Strategy by fully conforming to Dependency Injection Principle (DIP) allows each detailed implementation to be manipulated by many different generic algorithms.
//Which the same way to solve a problem
//Template Method uses Inheritance
//Strategy uses Composition/Delegation
abstract class TemplateMethod{
public final void execute() {
doFirstThing();
doSecondthing();
}
//modifier can be public, private, protected
abstract void doFirstThing();
abstract void doSecondthing();
}
class FirstConcreateTemplateMethod extends TemplateMethod{
@Override
void doFirstThing() {}
@Override
void doSecondthing() {}
}
class SecondConcreateTemplateMethod extends TemplateMethod{
@Override
void doFirstThing() {}
@Override
void doSecondthing() {}
}
class Strategy{
private Strategable strategable; //the concrete implementation is interchangeable
public void execute() {
strategable.doFirstThing();
strategable.doSecondthing();
}
}
interface Strategable{
//modifier always is public
void doFirstThing();
void doSecondthing();
}
class FirstConcreteStrategy implements Strategable{
@Override
public void doFirstThing() {}
@Override
public void doSecondthing() {}
}

References:
[1]. Bert Bates, Kathy Sierra, Eric Freeman, and Elisabeth Robson, Head First Design Patterns, A Brain-Friendly Guide
[2]. Robert C. Martin, Agile Software Development, Principles, Patterns, and Practices
[3]. https://en.wikipedia.org/wiki/Template_method_pattern

Comments

Popular posts from this blog

[Snippet] CSS - Child element overlap parent

I searched from somewhere and found that a lot of people says a basic concept for implementing this feature looks like below: HTML code: <div id="parent">  <div id="child">  </div> </div> And, CSS: #parent{   position: relative;   overflow:hidden; } #child{   position: absolute;   top: -1;   right: -1px; } However, I had a lot of grand-parents in my case and the above code didn't work. Therefore, I needed an alternative. I presumed that my app uses Boostrap and AngularJs, maybe some CSS from them affects mine. I didn't know exactly the problem, but I believed when all CSS is loaded into my browser, I could completely handle it. www.tom-collinson.com I tried to create an example to investigated this problem by Fiddle . Accidentally, I just changed: position: parent; to position: static; for one of parents -> the problem is solved. Look at my code: <div class="modal-body dn-placeholder-parent-positi...

Coding Exercise, Episode 1

I have received the following exercise from an interviewer, he didn't give the name of the problem. Honestly, I have no idea how to solve this problem even I have tried to read it three times before. Since I used to be a person who always tells myself "I am not the one good at algorithms", but giving up something too soon which I feel that I didn't spend enough effort to overcome is not my way. Then, I have sticked on it for 24 hours. According to the given image on the problem, I tried to get more clues by searching. Thanks to Google, I found a similar problem on Hackerrank (attached link below). My target here was trying my best to just understand the problem and was trying to solve it accordingly by the Editorial on Hackerrank. Due to this circumstance, it turns me to love solving algorithms from now on (laugh). Check it out! Problem You are given a very organized square of size N (1-based index) and a list of S commands The i th command will follow t...

DevOps for Dummies

Everyone talks about it, but not everyone knows what it is. Why DevOps? In general, whenever an organization adopts any new technology, methodology, or approach, that adoption has to be driven by a business need. Any kind of system that need rapid delivery of innovation requires DevOps (development and operations). Why? DevOps requires mechanisms to get fast feedback from all the stakeholders in the software application that's being delivered. DevOps approaches to reduce waste and rework and to shift resources to higher-value activities. DevOps aims to deliver value (of organization or project) faster and more efficiently. DevOps Capabilities The capabilities that make up DevOps are a broad set that span the software delivery life cycle. The following picture is a reference architecture which provides a template of a proven solution by using a set of preferred methods and capabilities. My Remarks Okay, that sounds cool. What does it simply mean, again? The f...

How did I start practising BDD?

In the beginning days, I have practiced TDD (Test Driven Development) using JUnit, I approached that I should test methods belong to a class. For example: I have a class with some methods: public class A{ public void method1(){ } public void method2(){ } } And then, I wrote some test methods to check the corresponding ones, for example: public class ATest{ @Test public void testMethod1(){ .... assertTrue(...); ..... assertEquals(...); } @Test public void testMethod2(){ } } After that, I know that a test method (ex: testMethod1) should just only test one thing, so I decided to write more methods for each case. It looks like the following: @Test public void testMethod1_When_Case1(){ .... assertTrue(...); } @Test public void testMethod1_When_Case2(){ .... assertEquals(...); } However, it was not a really good approach because it seems that I just focused on test the functionality of the method of the class. With the TDD approach, I knew that I s...

Selenium - Override javascript functions to ignore downloading process

I have got an issue with downloading process on IE 8. This browser blocks my automatic-download functionality on my app so that I could not work with my test case any more after that. In my case, I didn't care about the file is downloaded or not, I just focus on the result after downloading process finished successfully. Therefore, I found a solution to ignore this process so that I can work normally. I use Primefaces, here is the remote command to trigger the download process <p:remoteCommand name="cmdGenerateDocument" actionListener="#{logic.onGenerateDocument}" update="xrflDocumentCreationPanel" oncomplete="clickDownloadButton();"/> The following is my test case: @Test public void shouldUpdateStep6ToWarningIfStep1IsValidAfterFinished(){ MainPage mainPage = new MainPage(); waitForLoading(mainPage.getDriver()); EmployeeDetailPage empDetailPage = new EmployeeDetailPage(); waitForLoading(empDetailPage.getDriver()); e...