Template Method Design Pattern: Concepts, Implementation, and Usage
The Template Method pattern defines an algorithm’s fixed skeleton in an abstract class while delegating variable steps to subclasses via abstract or hook methods, enabling reusable, maintainable code through a final template method, concrete implementations, and practical examples such as online shopping and JDK’s AbstractList, with benefits of encapsulation and extensibility but potential complexity from inheritance.
Software development aims for maintainable and extensible code; design patterns help achieve reuse and low coupling. This article focuses on the Template Method pattern, a behavioral pattern.
Core concept : Define the algorithm skeleton in an abstract class, defer variable steps to subclasses via abstract or hook methods.
Structure : Abstract class (defines template method and primitive operations) and concrete subclasses (implement the primitive operations).
Implementation steps :
Create an abstract class with a final template method.
Declare abstract methods for variable steps and optional hook methods.
Implement concrete subclasses that provide specific behavior.
Code example (online shopping process):
// abstract parent class defining the algorithm skeleton
public abstract class TMAbstractClass {
public final void shopOnline() {
selectItems();
checkoutItems();
if (isReturnItemsHook1()) {
returnItems();
} else if (isExchangeItemsHook2()) {
exchangeItems();
// assume exchange resolves the order
confirmTheReceipt();
} else {
confirmTheReceipt();
}
terminateTransaction();
}
protected abstract void selectItems();
protected void checkoutItems() { System.out.println("下单支付"); }
public boolean isReturnItemsHook1() { return false; }
protected void returnItems() {}
public boolean isExchangeItemsHook2() { return false; }
protected void exchangeItems() {}
protected void confirmTheReceipt() { System.out.println("确认收货"); }
protected void terminateTransaction() { System.out.println("终止交易"); }
}
// concrete subclass 1
public class TMConcreteClass1 extends TMAbstractClass {
@Override protected void selectItems() { System.out.println("选择商品1"); }
@Override public boolean isReturnItemsHook1() { return true; }
@Override protected void returnItems() { System.out.println("退货退款"); }
}
// concrete subclass 2
public class TMConcreteClass2 extends TMAbstractClass {
@Override protected void selectItems() { System.out.println("选择商品2"); }
@Override public boolean isExchangeItemsHook2() { return true; }
@Override protected void exchangeItems() { System.out.println("换货"); }
}
// client
public class userPayForItem {
public static void main(String[] args) {
System.out.println("购物记录1:");
TMAbstractClass shopRecord1 = new TMConcreteClass1();
shopRecord1.shopOnline();
System.out.println();
System.out.println("购物记录2:");
TMConcreteClass2 shopRecord2 = new TMConcreteClass2();
shopRecord2.shopOnline();
}
}The output demonstrates how different hooks affect the algorithm flow.
JDK source illustration : AbstractList’s addAll method follows the template method pattern, delegating element addition to add which subclasses may override. The corresponding ArrayList implementation shows a concrete version.
public abstract class AbstractList
extends AbstractCollection
implements List
{
public boolean addAll(int index, Collection
c) {
rangeCheckForAdd(index);
boolean modified = false;
for (E e : c) {
add(index++, e);
modified = true;
}
return modified;
}
}
public class ArrayList
extends AbstractList
{
public boolean addAll(int index, Collection
c) {
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew);
int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew, numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
}Advantages :
Encapsulates invariant parts while allowing variation.
Extracts common code for easier maintenance.
Controls behavior in the superclass; subclasses extend functionality, adhering to the Open/Closed principle.
Disadvantages :
Subclass behavior can affect superclass logic, increasing complexity.
May lead to excessive inheritance.
Applicable scenarios :
When the overall algorithm is stable but some steps vary.
When multiple subclasses share common behavior.
When controlled extension points (hooks) are needed.
In summary, the Template Method pattern provides a simple inheritance structure to separate fixed and variable parts of an algorithm, promoting reuse and maintainability.
DaTaobao Tech
Official account of DaTaobao Technology
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.