Fundamentals 16 min read

Understanding the Template Method Design Pattern with Java Examples

This article explains the Template Method design pattern, illustrating its structure with Java drink‑making examples, discussing hook methods, and showing real‑world usages in JDK’s Comparable and Spring’s ApplicationContext, while highlighting advantages, drawbacks, and practical scenarios.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Understanding the Template Method Design Pattern with Java Examples

Introduction

Template Method is a behavioral design pattern that defines the skeleton of an algorithm in a superclass while allowing subclasses to override specific steps without changing the overall structure.

Scenario Example

Using a beverage shop analogy, the article first shows a naive interface‑based design and then refactors it into an abstract class Drinks with a final method makingDrinks() that outlines the fixed steps (boil water, brew, pour, add condiments). The invariant steps are implemented in the abstract class, while the variable steps are declared abstract for subclasses.

<code style="padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px"><span style="color: #c678dd; line-height: 26px">public</span> <span style="color: #c678dd; line-height: 26px">abstract</span> <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">class</span> <span style="color: #e6c07b; line-height: 26px">Drinks</span> </span>{<br/><br/>    <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">void</span> <span style="color: #61aeee; line-height: 26px">boilWater</span><span style="line-height: 26px">()</span> </span>{<br/>        System.out.println(<span style="color: #98c379; line-height: 26px">"将水煮沸"</span>);<br/>    }<br/><br/>    <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">abstract</span> <span style="color: #c678dd; line-height: 26px">void</span> <span style="color: #61aeee; line-height: 26px">brew</span><span style="line-height: 26px">()</span></span>;<br/><br/>    <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">void</span> <span style="color: #61aeee; line-height: 26px">pourInCup</span><span style="line-height: 26px">()</span> </span>{<br/>        System.out.println(<span style="color: #98c379; line-height: 26px">"倒入杯子"</span>);<br/>    }<br/><br/>    <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">abstract</span> <span style="color: #c678dd; line-height: 26px">void</span> <span style="color: #61aeee; line-height: 26px">addCondiments</span><span style="line-height: 26px">()</span></span>;<br/>    <br/>    <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">public</span> <span style="color: #c678dd; line-height: 26px">final</span> <span style="color: #c678dd; line-height: 26px">void</span> <span style="color: #61aeee; line-height: 26px">makingDrinks</span><span style="line-height: 26px">()</span> </span>{<br/>        <span style="color: #5c6370; font-style: italic; line-height: 26px">//热水</span><br/>        boilWater();<br/>        <span style="color: #5c6370; font-style: italic; line-height: 26px">//冲泡</span><br/>        brew();<br/>        <span style="color: #5c6370; font-style: italic; line-height: 26px">//倒进杯子</span><br/>        pourInCup();<br/>        <span style="color: #5c6370; font-style: italic; line-height: 26px">//加料</span><br/>        addCondiments();<br/>    }<br/>}<br/></code>

Concrete subclasses Tea and Coffee extend Drinks and implement the abstract methods to provide specific brewing and condiment logic.

<code style="padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px"><span style="color: #c678dd; line-height: 26px">public</span> <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">class</span> <span style="color: #e6c07b; line-height: 26px">Tea</span> <span style="color: #c678dd; line-height: 26px">extends</span> <span style="color: #e6c07b; line-height: 26px">Drinks</span> </span>{<br/>    <span style="color: #61aeee; line-height: 26px">@Override</span><br/>    <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">void</span> <span style="color: #61aeee; line-height: 26px">brew</span><span style="line-height: 26px">()</span> </span>{<br/>        System.out.println(<span style="color: #98c379; line-height: 26px">"冲茶叶"</span>);<br/>    }<br/>    <span style="color: #61aeee; line-height: 26px">@Override</span><br/>    <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">void</span> <span style="color: #61aeee; line-height: 26px">addCondiments</span><span style="line-height: 26px">()</span> </span>{<br/>        System.out.println(<span style="color: #98c379; line-height: 26px">"加柠檬片"</span>);<br/>    }<br/>}<br/></code>
<code style="padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px"><span style="color: #c678dd; line-height: 26px">public</span> <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">class</span> <span style="color: #e6c07b; line-height: 26px">Coffee</span> <span style="color: #c678dd; line-height: 26px">extends</span> <span style="color: #e6c07b; line-height: 26px">Drinks</span> </span>{<br/>    <span style="color: #61aeee; line-height: 26px">@Override</span><br/>    <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">void</span> <span style="color: #61aeee; line-height: 26px">brew</span><span style="line-height: 26px">()</span> </span>{<br/>        System.out.println(<span style="color: #98c379; line-height: 26px">"冲咖啡粉"</span>);<br/>    }<br/><br/>    <span style="color: #61aeee; line-height: 26px">@Override</span><br/>    <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">void</span> <span style="color: #61aeee; line-height: 26px">addCondiments</span><span style="line-height: 26px">()</span> </span>{<br/>        System.out.println(<span style="color: #98c379; line-height: 26px">"加奶加糖"</span>);<br/>    }<br/>}<br/></code>

A main method demonstrates creating Coffee and Tea objects and invoking makingDrinks() to see the template in action.

<code style="padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px"><span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">public</span> <span style="color: #c678dd; line-height: 26px">static</span> <span style="color: #c678dd; line-height: 26px">void</span> <span style="color: #61aeee; line-height: 26px">main</span><span style="line-height: 26px">(String[] args)</span> </span>{<br/>    Drinks coffee = <span style="color: #c678dd; line-height: 26px">new</span> Coffee();<br/>    coffee.makingDrinks();<br/>    System.out.println();<br/>    Drinks tea = <span style="color: #c678dd; line-height: 26px">new</span> Tea();<br/>    tea.makingDrinks();<br/>}<br/></code>

Hook Method

The article introduces a hook method customerLike() that can be overridden by subclasses to decide whether to add condiments, demonstrating how optional steps can be controlled.

<code style="padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px"><span style="color: #c678dd; line-height: 26px">public</span> <span style="color: #c678dd; line-height: 26px">abstract</span> <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">class</span> <span style="color: #e6c07b; line-height: 26px">Drinks</span> </span>{<br/><br/>    ...<br/><br/>    <span style="color: #c678dd; line-height: 26px">public</span> <span style="color: #c678dd; line-height: 26px">final</span> <span style="color: #c678dd; line-height: 26px">void</span> <span style="color: #61aeee; line-height: 26px">makingDrinks</span><span style="line-height: 26px">()</span> {<br/>        boilWater();<br/>        brew();<br/>        pourInCup();<br/>        <span style="color: #5c6370; font-style: italic; line-height: 26px">//如果顾客需要,才加料</span><br/>        <span style="color: #c678dd; line-height: 26px">if</span> (customerLike()) {<br/>            addCondiments();<br/>        }<br/>    }<br/><br/>    <span style="color: #5c6370; font-style: italic; line-height: 26px">//默认实现,返回 true</span><br/>    <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">boolean</span> <span style="color: #61aeee; line-height: 26px">customerLike</span><span style="line-height: 26px">()</span> </span>{<br/>        <span style="color: #c678dd; line-height: 26px">return</span> <span style="color: #c678dd; line-height: 26px">true</span>;<br/>    }<br/>}<br/></code>

Real‑World Uses

JDK Comparable

Implementing Comparable requires defining compareTo(), which is called by Collections.sort() or Arrays.sort(). The sorting algorithm is a template method that invokes the user‑provided compareTo for each comparison.

<code style="padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px"><span style="color: #c678dd; line-height: 26px">public</span> <span style="color: #c678dd; line-height: 26px">int</span> <span style="color: #61aeee; line-height: 26px">compareTo</span><span style="line-height: 26px">(Object o)</span> {<br/>    Coffee coffee = (Coffee)o;<br/>    if(this.price < coffee.price) <span style="color: #c678dd; line-height: 26px">return</span> -1;<br/>    else if(this.price == coffee.price) <span style="color: #c678dd; line-height: 26px">return</span> 0;<br/>    else <span style="color: #c678dd; line-height: 26px">return</span> 1;<br/>}<br/></code>

Spring ApplicationContext

Spring’s AbstractApplicationContext.refresh() method is a classic template method. It defines the overall container startup workflow while delegating specific steps (e.g., getBeanFactory(), refreshBeanFactory()) to subclasses and providing hook points such as postProcessBeanFactory().

<code style="padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px"><span style="color: #c678dd; line-height: 26px">public</span> <span style="color: #c678dd; line-height: 26px">abstract</span> <span style="line-height: 26px"><span style="color: #c678dd; line-height: 26px">class</span> <span style="color: #e6c07b; line-height: 26px">AbstractApplicationContext</span> <span style="color: #c678dd; line-height: 26px">extends</span> <span style="color: #e6c07b; line-height: 26px">DefaultResourceLoader</span> {<br/>    <span style="color: #61aeee; line-height: 26px">@Override</span><br/>    <span style="color: #c678dd; line-height: 26px">public</span> <span style="color: #c678dd; line-height: 26px">void</span> <span style="color: #61aeee; line-height: 26px">refresh</span><span style="line-height: 26px">()</span> {<br/>        synchronized(this.startupShutdownMonitor){<br/>            prepareRefresh();<br/>            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();<br/>            prepareBeanFactory(beanFactory);<br/>            postProcessBeanFactory(beanFactory);<br/>            // … other steps …<br/>            finishRefresh();<br/>        }<br/>    }<br/>    <span style="color: #c678dd; line-height: 26px">protected</span> <span style="color: #c678dd; line-height: 26px">void</span> <span style="color: #61aeee; line-height: 26px">postProcessBeanFactory</span>(ConfigurableListableBeanFactory beanFactory){ }<br/>}<br/></code>

Summary

Advantages: encapsulates invariant parts, promotes code reuse, and centralizes algorithm control in the superclass.

Disadvantages: each variation requires a new subclass, potentially increasing class count and system complexity.

When to use: multiple subclasses share a common algorithm structure, or a complex method benefits from being broken into a fixed template with customizable steps.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaspringJDKdesign patternTemplate MethodInheritanceHook Method
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.