iTranslated by AI
[TS] Back to Basics: The Template Method Pattern
Introduction
In this article, I will explain the Template Method Pattern.
It is a design pattern that defines the framework of a process and allows subclasses to handle the specific implementations, making the overall structure more flexible and manageable.
What is the Template Method Pattern?
There is an explanation by TECHSCORE.
- Reference: TECHSCORE | TemplateMethod Pattern
Below is a quotation from the site:
Chapter 3 introduces the
TemplateMethodpattern. Atemplateis a thin plastic plate with holes in the shape of letters. By tracing those holes with a pen, you can write neat characters even by hand. However, depending on whether you use a marker, a pencil, or ink and a brush, the actual appearance of the characters will vary. Thetemplatesimply provides the framework that determines the shape.The
TemplateMethodpattern is a pattern that functions like a template. You define the framework of a process in a superclass and implement the specific content in subclasses. In the superclass, you define the abstract methods to be used within the flow of the algorithm, as well as thetemplateMethodwhich defines the algorithm of the process using these abstract methods.
The key point is "defining the framework of a process in a superclass."
The superclass defines only the framework, and what is actually performed depends on the implementation of the subclasses.
Digression
It might be easier to understand if you are familiar with "template literals" often seen in TypeScript or JavaScript.
const zenn: string = 'ZennTaro';
console.log(`Hello, ${zenn}!`); // --> Hello, ZennTaro!
Template literals also have a fixed base template (the "Hello, ...!" part in the code), where a specific value like zenn is then inserted.
I have explained template literals in the following article, so please take a look if you are interested:
Example Case
I'd like to define a class for sending emails.
An email consists of a "Subject," "Body," and "Footer," as shown in the following class:
class Mail {
title: string = '';
body: string = '';
footer: string = '';
}
When considering a class called MailSender to send this email, the content of the subject, body, and footer will vary depending on the creator.
For example, there might be cases where you "write an email in English," "write an email with formal content," or conversely, "write an email with casual content."
The key point above is that the process of "writing the subject, body, and footer before sending" is common to all cases.
Therefore, in this situation, we can use the Template Method pattern.
MailSender will define the framework of the send() process, and the functions that generate the email content will not be defined here.
abstract class MailSender {
/** Write the subject */
abstract writeTitle(mail: Mail):void;
/** Write the body */
abstract writeBody(mail: Mail):void;
/** Write the footer */
abstract writeFooter(mail: Mail):void;
/** Sending process */
send = () => {
let mail = new Mail();
this.writeTitle(mail);
this.writeBody(mail);
this.writeFooter(mail);
// Console output (assumed to be sent)
console.log(mail);
}
}
send() starts with writeTitle, and after writing various contents, it outputs the email to be sent to the console.
By implementing this MailSender, you can generate subclasses that satisfy the framework of "sending an email."
class JapaneseMailSender extends MailSender {
writeTitle = (mail: Mail) => mail.title = 'Subject (Japanese)';
writeBody = (mail: Mail) => mail.body = 'Body (Japanese)';
writeFooter = (mail: Mail) => mail.footer = 'Footer (Japanese)';
}
class EnglishMailSender extends MailSender {
writeTitle = (mail: Mail) => mail.title = 'Title';
writeBody = (mail: Mail) => mail.body = 'Body';
writeFooter = (mail: Mail) => mail.footer = 'Footer';
}
const jp: JapaneseMailSender = new JapaneseMailSender();
jp.send(); // --> { title: 'Subject (Japanese)', body: 'Body (Japanese)', footer: 'Footer (Japanese)' }
const en: EnglishMailSender = new EnglishMailSender();
en.send(); // --> { title: 'Title', body: 'Body', footer: 'Footer' }
Summary
In this article, I introduced the Template Method Pattern, one of the design patterns, using TypeScript.
The characteristic feature is that by "defining the framework of a process," you can implement subclasses that follow that framework.
The advantage is that you can keep the overall outline of the process while freely managing only the internal content.
Since it is one of the relatively easy-to-adopt design patterns among the GoF (Gang of Four) patterns, why not give it a try?
Discussion